class GtkRadioButton(AutopilotGtkEmulatorBase): """ Emulator for a GtkRadioButton instance """ def __init__(self, *args): super(GtkRadioButton, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def click(self, ): """ Clicks a GtkRadioButton If the Radio button is not already active, click and wait for active to be true """ if self.active == 1: logger.debug('Object already selected. Returning') return # now click it self.pointing_device.click_object(self) # now wait for state to change self.active.wait_for(1) logger.debug('Object clicked and and selected. Active state changed ' 'successfully') def check(self, visible=True): expectThat(self.label).is_unicode() expectThat(self.label).not_equals( u'', msg="Expected {0} label to contain text, but its empty".format( self.name)) expectThat(self.visible).equals( visible, msg="Expected {0} label to be visible, but its wasn't".format( self.name))
class GtkTextView(AutopilotGtkEmulatorBase): def __init__(self, *args): super(GtkTextView, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() @log_action(logging.info) def enter_text(self, text): """ Enter given text into a GtkTextView widget Function will delete any text currently in the buffer when called params: :text: String of text to enter in the entry """ self._get_focus() assert self.is_focus == 1 # if the entry is not empty lets empty it first if self.buffer != '': self.kbd.press_and_release('Ctrl+a') self.kbd.press_and_release('Delete') assert self.buffer == '' self.kbd.type(text) if self.buffer != text: raise EmulatorTypoException( "Typo Found: The text was not entered correctly. \ The GtkTextView contains: '{0}' but should have been: '{1}'. \ Possible causes are: The textview did not clear correctly before \ entering text, or the keyboard mistyped".format( self.buffer, text)) #TODO: would it be good to return the buffer? def _get_focus(self, ): self.pointing_device.click_object(self) self.is_focus.wait_for(1)
class GtkRadioButton(AutopilotGtkEmulatorBase): """ Emulator for a GtkRadioButton instance """ def __init__(self, *args): super(GtkRadioButton, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def click(self, ): """ Clicks a GtkRadioButton If the Radio button is not already active, click and wait for active to be true """ if self.active == 1: logger.debug('Object already selected. Returning') return # now click it self.pointing_device.click_object(self) # now wait for state to change self.active.wait_for(1) logger.debug( 'Object clicked and and selected. Active state changed ' 'successfully') def check(self, visible=True): expectThat(self.label).is_unicode() expectThat(self.label).not_equals( u'', msg="Expected {0} label to contain text, but its empty" .format(self.name)) expectThat(self.visible).equals( visible, msg="Expected {0} label to be visible, but its wasn't" .format(self.name))
class InputEventDelayTests(MockAppMouseTestBase, TestWithScenarios): scenarios = [ ('Touch', dict(input_class=Touch)), ('Mouse', dict(input_class=Mouse)), ] def setUp(self): super(InputEventDelayTests, self).setUp() self.device = Pointer(self.input_class.create()) self.widget = self.get_mock_app_main_widget() def get_mock_app_main_widget(self): self.app = self.start_mock_app() return self.app.select_single('MouseTestWidget') def test_subsequent_events_delay(self): with ElapsedTimeCounter() as time_counter: for i in range(3): self.device.click_object(self.widget, time_between_events=0.6) self.assertThat(time_counter.elapsed_time, GreaterThan(1.0)) def test_subsequent_events_default_delay(self): with ElapsedTimeCounter() as time_counter: for i in range(10): self.device.click_object(self.widget) self.assertThat(time_counter.elapsed_time, GreaterThan(0.9))
class GtkButtonAccessible(AutopilotGtkEmulatorBase): def __init__(self, *args): super(GtkButtonAccessible, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def click(self, ): logger.debug('Clicking {0} item'.format(self.accessible_name)) self.pointing_device.click_object(self)
class GtkTextCellAccessible(AutopilotGtkEmulatorBase): def __init__(self, *args): super(GtkTextCellAccessible, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def click(self, ): logger.debug('Clicking tree item') self.pointing_device.click_object(self)
class GtkTreeView(AutopilotGtkEmulatorBase): """ Emulator for a GtkTreeView instance """ def __init__(self, *args): super(GtkTreeView, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) @log_action(logging.info) def click(self, ): """ This simply clicks a treeview object """ self.pointing_device.click_object(self) assert self.is_focus == 1 @log_action(logging.info) def select_item(self, label_text): """ Selects an item in a GtkTreeView by its UI label text :param label_text: The label value of the tree item as seen on the UI :returns: An object of the requested treeitem e.g. If you want to click say an item displaying 'Home' in a treeview then it would be:: >>> treeitem = treeview.select_item('Home') also see GtkFileChooserDialog.go_to_directory() for another example if for some reason this doesn't work then use the .click() function to get the treeviews focus """ treeview = self._get_gail_treeview() # if we can't get the gail treeview lets try a full scan if treeview is None: root = self.get_root_instance() treeview_item = root.select_single('GtkCellTextAccessible', accessible_name=str(label_text)) assert treeview_item is not None return treeview_item #and now select the item from within the GAILTreeView. item = treeview.select_item(str(label_text)) assert item is not None return item def _get_gail_treeview(self, ): """ Gets the GtkTreeViews corresponding GtkTreeViewAccessible object """ # lets get a root instance root = self.get_root_instance() assert root is not None # As the treeview item is in the GAILWindow tree and not our current tree # We want to select the treeviewaccessible with the same globalRect as us treeviews = root.select_many('GtkTreeViewAccessible', globalRect=self.globalRect) # if the treeviews are nested they could potentially have the # same globalRect so lets pick out the one thats visible for treeview in treeviews: if treeview.visible == True: return treeview
class GtkSwitch(AutopilotGtkEmulatorBase): """ Emulator for a GtkSwitch instance """ def __init__(self, *args): super(GtkSwitch, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) @log_action(logging.info) def click(self, ): #TODO: add checks to assert the switched changed state self.pointing_device.click_object(self)
class GtkLabel(AutopilotGtkEmulatorBase): """ Emulator for a GtkLabel Instance""" def __init__(self, *args): super(GtkLabel, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) @log_action(logging.info) def click(self, ): """ Clicks on a GtkLabel """ self.pointing_device.click_object(self)
class GtkTextCellAccessible(AutopilotGtkEmulatorBase): def __init__(self, *args): super(GtkTextCellAccessible, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) @log_action(logging.info) def click(self, ): #TODO: raise an error if the object has negative global rect's as these can't be clicked self.pointing_device.click_object(self)
class GtkEntry(AutopilotGtkEmulatorBase): """ Emulator for a GtkEntry widget """ def __init__(self, *args): super(GtkEntry, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() def click(self, ): """ Click on GtkEntry """ self.pointing_device.click_object(self)
class GtkAlignment(GtkContainers): """ Emulator class for a GtkAlignment instance """ def __init__(self, *args): super(GtkAlignment, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() def enter_crypto_phrase(self, crypto_phrase): if self.name == 'stepPartCrypto': while True: self._enter_pass_phrase(crypto_phrase) match = self._check_crypto_phrase_match() if match: break else: raise ValueError("enter_crypto_phrase() can only be called from " "stepPartCrypto page object") def _enter_pass_phrase(self, phrase): pwd_entries = ['password', 'verified_password'] for i in pwd_entries: entry = self.select_single(BuilderName=i) with self.kbd.focused_type(entry) as kb: kb.press_and_release('Ctrl+a') kb.press_and_release('Delete') expectThat(entry.text).equals( u'', msg='{0} entry text was not cleared properly' .format(entry.name)) kb.type(phrase) def _check_crypto_phrase_match(self, ): pwd1 = self.select_single(BuilderName='password').text pwd2 = self.select_single(BuilderName='verified_password').text if pwd1 == pwd2: return True else: return False def create_new_partition_table(self, ): if self.name == 'stepPartAdvanced': new_partition_button = self.select_single( BuilderName='partition_button_new_label') self.pointing_device.click_object(new_partition_button) time.sleep(5) self.kbd.press_and_release('Right') self.kbd.press_and_release('Enter') time.sleep(5) else: raise ValueError("create_new_partition_table() can only be called " "from stepPartAdvanced page object")
class GtkAlignment(GtkContainers): """ Emulator class for a GtkAlignment instance """ def __init__(self, *args): super(GtkAlignment, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() def enter_crypto_phrase(self, crypto_phrase): if self.name == 'stepPartCrypto': while True: self._enter_pass_phrase(crypto_phrase) match = self._check_crypto_phrase_match() if match: break else: raise ValueError("enter_crypto_phrase() can only be called from " "stepPartCrypto page object") def _enter_pass_phrase(self, phrase): pwd_entries = ['password', 'verified_password'] for i in pwd_entries: entry = self.select_single(BuilderName=i) with self.kbd.focused_type(entry) as kb: kb.press_and_release('Ctrl+a') kb.press_and_release('Delete') expectThat(entry.text).equals( u'', msg='{0} entry text was not cleared properly'.format( entry.name)) kb.type(phrase) def _check_crypto_phrase_match(self, ): pwd1 = self.select_single(BuilderName='password').text pwd2 = self.select_single(BuilderName='verified_password').text if pwd1 == pwd2: return True else: return False def create_new_partition_table(self, ): if self.name == 'stepPartAdvanced': new_partition_button = self.select_single( BuilderName='partition_button_new_label') self.pointing_device.click_object(new_partition_button) time.sleep(5) self.kbd.press_and_release('Right') self.kbd.press_and_release('Enter') time.sleep(5) else: raise ValueError("create_new_partition_table() can only be called " "from stepPartAdvanced page object")
class GtkComboBoxText(AutopilotGtkEmulatorBase): def __init__(self, *args): super(GtkComboBoxText, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) @log_action(logging.info) def click(self, ): #TODO: setup state changes #get current state i.e is it already open? #now click it self.pointing_device.click_object(self)
def test_can_type_string(self): """Typing text must produce the expected characters in the input field. """ text_area = self.launch_test_input_area() keyboard = Keyboard.create('OSK') pointer = Pointer(Touch.create()) pointer.click_object(text_area) keyboard._keyboard.wait_for_keyboard_ready() keyboard.type(self.input) self.assertThat(text_area.text, Eventually(Equals(self.input)))
class GtkRadioButton(AutopilotGtkEmulatorBase): """ Emulator for a GtkRadioButton instance """ def __init__(self, *args): super(GtkRadioButton, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) @log_action(logging.info) def click(self, ): """ Clicks a GtkRadioButton, and waits for the active state (checked/notchecked) to change after being clicked """ #get current state new_val = 0 if self.active == 0: new_val = 1 #now click it self.pointing_device.click_object(self) #now wait for state to change self.active.wait_for(new_val)
class GtkButton(AutopilotGtkEmulatorBase): """ Emulator for a GtkButton Instance """ def __init__(self, *args): super(GtkButton, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) @log_action(logging.info) def click(self, ): """ Clicks a GtkButton widget On some occasions you may need to wait for a button to become sensitive. So when calling this function if the sensitive property is 0 it will wait for 10 seconds for button to become sensitive before clicking """ #sometimes we may need to wait for the button to become clickable # so lets wait for it if we do if self.sensitive == 0: self.sensitive.wait_for(1) self.pointing_device.click_object(self)
class GtkButton(AutopilotGtkEmulatorBase): """ Emulator for a GtkButton Instance """ def __init__(self, *args): super(GtkButton, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) @log_action(logging.info) def click(self,): """ Clicks a GtkButton widget On some occasions you may need to wait for a button to become sensitive. So when calling this function if the sensitive property is 0 it will wait for 10 seconds for button to become sensitive before clicking """ #sometimes we may need to wait for the button to become clickable # so lets wait for it if we do if self.sensitive == 0: self.sensitive.wait_for(1) self.pointing_device.click_object(self)
class GtkLabel(AutopilotGtkEmulatorBase): """ Emulator for a GtkLabel Instance""" def __init__(self, *args): super(GtkLabel, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def click(self, ): """ Clicks on a GtkLabel """ logger.debug('Clicking "{0}" label'.format(self.name)) self.pointing_device.click_object(self) def check(self, visible=True): expectThat(self.label).is_unicode() expectThat(self.label).not_equals( u'', msg="Expected {0} label to contain text, but its empty".format( self.name)) expectThat(self.visible).equals( visible, msg="Expected {0} label to be visible, but its wasn't".format( self.name))
class GtkLabel(AutopilotGtkEmulatorBase): """ Emulator for a GtkLabel Instance""" def __init__(self, *args): super(GtkLabel, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def click(self, ): """ Clicks on a GtkLabel """ logger.debug('Clicking "{0}" label'.format(self.name)) self.pointing_device.click_object(self) def check(self, visible=True): expectThat(self.label).is_unicode() expectThat(self.label).not_equals( u'', msg="Expected {0} label to contain text, but its empty" .format(self.name)) expectThat(self.visible).equals( visible, msg="Expected {0} label to be visible, but its wasn't" .format(self.name))
class GtkEntry(AutopilotGtkEmulatorBase): """ Emulator for a GtkEntry widget """ def __init__(self, *args): super(GtkEntry, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() def click(self, ): """ Click on GtkEntry """ self.pointing_device.click_object(self) @log_action(logging.info) def enter_text(self, text): """ Enters given text into a GtkEntry widget Does not require GtkEntry to be clicked first and will delete any text currently in the entry when called :param text: String of text to enter in the entry """ self._get_focus() assert self.is_focus == 1 # if the entry is not empty lets empty it first if self.text != '': self.kbd.press_and_release('Ctrl+a') self.kbd.press_and_release('Delete') assert self.text == '' self.kbd.type(text) if self.text != text: raise EmulatorTypoException( "Typo Found: The text was not entered correctly. \ The GtkEntry contains: '{0}' but should have been: '{1}'. \ Possible causes are: The entry did not clear correctly before \ entering text, or the keyboard mistyped".format(self.text, text)) def _get_focus(self, ): self.pointing_device.click_object(self) self.is_focus.wait_for(1)
class GtkEntry(AutopilotGtkEmulatorBase): """ Emulator for a GtkEntry widget """ def __init__(self, *args): super(GtkEntry, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() def click(self, ): """ Click on GtkEntry """ self.pointing_device.click_object(self) @log_action(logging.info) def enter_text(self, text): """ Enters given text into a GtkEntry widget Does not require GtkEntry to be clicked first and will delete any text currently in the entry when called :param text: String of text to enter in the entry """ self._get_focus() assert self.is_focus == 1 # if the entry is not empty lets empty it first if self.text != '': self.kbd.press_and_release('Ctrl+a') self.kbd.press_and_release('Delete') assert self.text == '' self.kbd.type(text) if self.text != text: raise EmulatorTypoException( "Typo Found: The text was not entered correctly. \ The GtkEntry contains: '{0}' but should have been: '{1}'. \ Possible causes are: The entry did not clear correctly before \ entering text, or the keyboard mistyped".format( self.text, text)) def _get_focus(self, ): self.pointing_device.click_object(self) self.is_focus.wait_for(1)
class GtkTextView(AutopilotGtkEmulatorBase): def __init__(self, *args): super(GtkTextView, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() @log_action(logging.info) def enter_text(self, text): """ Enter given text into a GtkTextView widget Function will delete any text currently in the buffer when called params: :text: String of text to enter in the entry """ self._get_focus() assert self.is_focus == 1 # if the entry is not empty lets empty it first if self.buffer != '': self.kbd.press_and_release('Ctrl+a') self.kbd.press_and_release('Delete') assert self.buffer == '' self.kbd.type(text) if self.buffer != text: raise EmulatorTypoException( "Typo Found: The text was not entered correctly. \ The GtkTextView contains: '{0}' but should have been: '{1}'. \ Possible causes are: The textview did not clear correctly before \ entering text, or the keyboard mistyped".format(self.buffer, text)) #TODO: would it be good to return the buffer? def _get_focus(self, ): self.pointing_device.click_object(self) self.is_focus.wait_for(1)
class GtkToggleButton(AutopilotGtkEmulatorBase): """ Emulator for a GtkToggleButton instance """ def __init__(self, *args): super(GtkToggleButton, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def check(self, visible=True): expectThat(self.label).is_unicode() expectThat(self.label).not_equals( u'', msg="Expected {0} label to contain text, but its empty" .format(self.name)) expectThat(self.visible).equals( visible, msg="Expected {0} label to be visible, but its wasn't" .format(self.name)) def click(self, ): """ Clicks a GtkToggleButton, and waits for the active state (toggled/nottoggled) to change after being clicked """ # get current state new_val = 0 if self.active == 0: new_val = 1 logger.debug('Objects current state is "{0}", ' 'the state after clicking should be "{1}"' .format(self.active, new_val)) # now click it self.pointing_device.click_object(self) # now wait for state to change self.active.wait_for(new_val) logger.debug('Object clicked, state change successful')
class GtkToggleButton(AutopilotGtkEmulatorBase): """ Emulator for a GtkToggleButton instance """ def __init__(self, *args): super(GtkToggleButton, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def check(self, visible=True): expectThat(self.label).is_unicode() expectThat(self.label).not_equals( u'', msg="Expected {0} label to contain text, but its empty".format( self.name)) expectThat(self.visible).equals( visible, msg="Expected {0} label to be visible, but its wasn't".format( self.name)) def click(self, ): """ Clicks a GtkToggleButton, and waits for the active state (toggled/nottoggled) to change after being clicked """ # get current state new_val = 0 if self.active == 0: new_val = 1 logger.debug('Objects current state is "{0}", ' 'the state after clicking should be "{1}"'.format( self.active, new_val)) # now click it self.pointing_device.click_object(self) # now wait for state to change self.active.wait_for(new_val) logger.debug('Object clicked, state change successful')
def _tap_key(self, key_rect, pointer=None): if pointer is None: pointer = Pointer(Touch.create()) pointer.click_object(key_rect)
class GtkComboBox(AutopilotGtkEmulatorBase): """ Emulator class for a GtComboBox instance""" def __init__(self, *args): super(GtkComboBox, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() def click(self, ): """Click Instance """ self.pointing_device.click_object(self) def select_item(self, labelText, enter=True): """ Selects an item in a GtkComboBox by its UI label text value :param labelText: The label value of the list item as seen on the UI :raises: **ValueError** when item is not in ComboBox list e.g. :: combobox = self.main_window.select_single('GtkComboBox') combobox.select_item('ListItem') If for some reason this doesn't work then use the :func:`click()` function to get the combobox focus """ logger.debug('Selecting "{0}" item'.format(labelText)) # get our gail combo to start combo = self._get_gail_combobox() # get total number of items in the combo items = combo.select_many('GtkMenuItemAccessible') self.click() # lets start at the top of the list self.kbd.press_and_release('Home') if enter: self.kbd.press_and_release('Enter') else: self.kbd.press_and_release('Down') # XXX: we should probably check the item is in the combo before # cycling through. for item in items: if labelText == combo.accessible_name: logger.debug('Item is now selected') return else: logger.debug('Go to next item in combo') self.kbd.press_and_release('Down') raise ValueError( 'Item with label text "{0}" was not found'.format(labelText)) def select_filesystem_format(self, fsFormat): logger.debug('Selecting "{0}" item'.format(fsFormat)) # get our gail combo to start combo = self._get_gail_combobox() # get total number of items in the combo items = combo.select_many('GtkMenuItemAccessible') self.click() # lets start at the top of the list self.kbd.press_and_release('Home') self.kbd.press_and_release('Enter') index = next((index for index, value in enumerate(items) if fsFormat == value.accessible_name), None) i = 0 while True: if i < index: self.kbd.press_and_release('Down') i += 1 else: assert i == index break def _get_gail_combobox(self, ): """ Gets the GtkComBox's corresponding GtkComboBoxAccessible object """ # lets get a root instance logger.debug('Getting corresponding GtkComboBoxAccessible object') root = self.get_root_instance() assert root is not None combos = root.select_many('GtkComboBoxAccessible', globalRect=self.globalRect) for combo in combos: if combo.visible: logger.debug('Combo found, returning combo') return combo raise ValueError("No ComboBox visible with globalRect {0}".format( self.globalRect))
class UbiquityAutopilotTestCase(UbiquityTestCase): def setUp(self): super(UbiquityAutopilotTestCase, self).setUp() self.app = self.launch_application() self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() self.current_page_title = '' self.previous_page_title = '' self.current_step = '' self.step_before = '' self.english_install = False english_label_conf.generate_config() self.english_config = configparser.ConfigParser() self.english_config.read('/tmp/english_config.ini') #delete config at end of test self.addCleanup(os.remove, '/tmp/english_config.ini') # always starts with 1 row ('/dev/sda') self.part_table_rows = 1 self.total_number_partitions = 0 def tearDown(self): self._check_no_visible_dialogs() super(UbiquityAutopilotTestCase, self).tearDown() unittest.TestCase.tearDown(self) def launch_application(self): ''' Hmm... launch ubiquity :returns: The application proxy object. ''' my_process = int(os.environ['UBIQUITY_PID']) my_dbus = str(os.environ['DBUS_SESSION_BUS_ADDRESS']) return get_proxy_object_for_existing_process( pid=my_process, dbus_bus=my_dbus, emulator_base=AutopilotGtkEmulatorBase) @property def main_window(self, ): return self.app.select_single('GtkWindow', name='live_installer') def go_to_next_page(self, wait=False): """ Goes to the next page of Ubiquity installer Will timeout after 2 mins waiting for next page to appear. Params: wait: If set to true will wait for the buttons sensitive property to be true. Will timeout after 20mins. NOTE: this should only be used when clicking 'Install Now' the default 2 mins is sufficient for every other page switch """ logger.debug('go_to_next_page(wait={0})'.format(wait)) nxt_button = self.main_window.select_single('GtkButton', name='next') nxt_button.click() if wait: # This sleep just bridges a weird error when the next button, # sometimes flickers its sensitive property back to 1 once clicked # and then goes back to 0 time.sleep(2) # now take back over from the sleep and wait for sensitive to # become 1 logger.debug("Waiting for 'next' Button to become sensitive " "again.....") self.assertThat(nxt_button.sensitive, Eventually(Equals(True), timeout=1200)) page_title = self.main_window.select_single( 'GtkLabel', name='page_title') self.assertThat(page_title.label, Eventually(NotEquals(self.current_page_title), timeout=120)) def go_to_progress_page(self, ): """ This simply clicks next and goes to the progress page NOTE: This shouldn't be used for any other page switches as it does no checks. """ nxt_button = self.main_window.select_single('GtkButton', name='next') nxt_button.click() def welcome_page_tests(self, lang=None): """ Runs the tests for the Welcome Page :param lang: The treeview label value (e.g 'English') of the required language. If None will pick a random language from the tree. ..NOTE: You should only specify a language if the test relies upon a specific language. It is better to write the tests to work for any language. """ self._update_current_step('stepLanguage') self._check_navigation_buttons() #first check pageTitle visible and correct if label given logger.debug("run_welcome_page_tests()") #selecting an install language logger.debug("Selecting stepLanguage page object") welcome_page = self.main_window.select_single( 'GtkBox', name='stepLanguage') treeview = welcome_page.select_single('GtkTreeView') #lets get all items treeview_items = treeview.get_all_items() #first lets check all the items are non-empty unicode strings logger.debug("Checking all tree items are valid unicode") for item in treeview_items: logger.debug("Check tree item with name '%s' is unicode" % item.accessible_name) self.expectIsInstance(item.accessible_name, str, "[Page:'stepLanguage'] Expected '%s' tree " "view item to be unicode but it wasn't" % item.accessible_name) self.expectThat(item.accessible_name, NotEquals(u''), "[Page:'stepLanguage'] Tree item found that " "doesn't contain any text") if lang: if lang == 'English': self.english_install = True item = treeview.select_item(lang) language = item else: language = welcome_page.get_random_language() if language == 'English': self.english_install = True welcome_page.select_language(language) self.assertThat(language.selected, Equals(True)) ##Test release notes label is visible logger.debug("Checking the release_notes_label") self.check_visible_object_with_label('release_notes_label') release_notes_label = welcome_page.select_single( BuilderName='release_notes_label') self.pointing_device.move_to_object(release_notes_label) self._update_page_titles() self._check_page_titles() self._check_navigation_buttons() def preparing_page_tests(self, updates=False, thirdParty=False, networkConnection=True, sufficientSpace=True, powerSource=False): """ Runs the tests for the 'Preparing to install' page :param updates: Boolean, if True selects install updates during install :param thirdParty: Boolean, if True selects install third-party software :param networkConnection: Boolean if True checks the network state box is visible and objects are correct, If false will still check the objects are correct but the state box is not visible :param sufficientSpace: Boolean if True checks the network state box is visible and objects are correct, If false will still check the objects are correct but the state box is not visible :param powerSource: Boolean if True checks the network state box is visible and objects are correct, If false will still check the objects are correct but the state box is not visible """ self._update_current_step('stepPrepare') self._check_navigation_buttons() self._update_page_titles() logger.debug("run_preparing_page_tests()") logger.debug("selecting stepPrepare page") preparing_page = self.main_window.select_single( 'GtkAlignment', BuilderName='stepPrepare') objList = ['prepare_best_results', 'prepare_foss_disclaimer', 'prepare_download_updates', 'prepare_nonfree_software'] self.check_visible_object_with_label(objList) if updates: logger.debug("Selecting install updates") update_checkbutton = preparing_page.select_single( 'GtkCheckButton', BuilderName='prepare_download_updates') self.pointing_device.click_object(update_checkbutton) if thirdParty: logger.debug("Selecting install thirdparty software") thrdprty_checkbutton = preparing_page.select_single( 'GtkCheckButton', BuilderName='prepare_nonfree_software') self.pointing_device.click_object(thrdprty_checkbutton) self._check_preparing_statebox('prepare_network_connection', visible=networkConnection) #and sufficient space self._check_preparing_statebox('prepare_sufficient_space', visible=sufficientSpace) # and power source self._check_preparing_statebox('prepare_power_source', visible=powerSource) self._check_page_titles() self._check_navigation_buttons() def edubuntu_addon_window_tests(self, unity=False, gnome=False, ltsp=False): """Run Page tests for edubuntu addon page""" self._update_current_step('edubuntu-addon_window') self._check_navigation_buttons() self._update_page_titles() add_on_page = self.main_window.select_single( 'GtkVBox', BuilderName='edubuntu-addon_window') page_objects = ['fallback_install', 'description', 'fallback_title', 'fallback_description', 'ltsp_install', 'ltsp_title', 'ltsp_description', 'ltsp_interface_label'] self.check_visible_object_with_label(page_objects) env = None if unity: logger.debug('Using default Unity env...') pass elif gnome: logger.debug("Using gnome fallback env") env = 'fallback_install' elif ltsp: logger.debug('Using LTSP env') env = 'ltsp_install' else: items = [None, 'fallback_install', 'ltsp_install'] env = random.choice(items) if env: choice = add_on_page.select_single(BuilderName=env) self.pointing_device.click_object(choice) self._check_page_titles() self._check_navigation_buttons() def edubuntu_packages_window_tests(self, ): """Run Page tests for edubuntu packages page""" self._update_current_step('edubuntu-packages_window') self._check_navigation_buttons() self._update_page_titles() self.check_visible_object_with_label('description') self._check_page_titles() self._check_navigation_buttons() def installation_type_page_tests(self, default=False, lvm=False, lvmEncrypt=False, custom=False): """Runs the tests for the installation type page :param default: Boolean if True will use the default selected option for the installation :param lvm: Boolean if True will use the LVM option for the installation :param lvmEncrypt: Boolean if True will use the LVM with encryption option for the installation :param custom: Boolean if True will use the 'Something else' option for the installation """ self._update_current_step('stepPartAsk') self._check_navigation_buttons() self._update_page_titles() option_name = None if default: from ubiquity_autopilot_tests.configs import default_install config = default_install if lvm: from ubiquity_autopilot_tests.configs import lvm_install config = lvm_install option_name = 'use_lvm' if lvmEncrypt: from ubiquity_autopilot_tests.configs import encrypt_lvm_install config = encrypt_lvm_install option_name = 'use_crypto' if custom: from ubiquity_autopilot_tests.configs import custom_install config = custom_install option_name = 'custom_partitioning' self.check_visible_object_with_label(config.visible_options) self.check_hidden_object_with_label(config.hidden_options) install_type_page = self.main_window.select_single( 'GtkAlignment', BuilderName='stepPartAsk') if option_name: obj = install_type_page.select_single(BuilderName=option_name) self.pointing_device.click_object(obj) self._check_page_titles() self._check_navigation_buttons() def lvm_crypto_page_tests(self, crypto_password): """ Runs the tests for the LVM encryption password page :param crypto_password: *String*, password to be used for the encryption """ self._update_current_step('stepPartCrypto') self._check_navigation_buttons() self._update_page_titles() logger.debug("run_step_part_crypto_page_tests({0})" .format(crypto_password)) logger.debug('Selecting stepPartCrypto page object') crypto_page = self.main_window.select_single( 'GtkAlignment', BuilderName='stepPartCrypto') items = ['verified_crypto_label', 'crypto_label', 'crypto_description', 'crypto_warning', 'crypto_extra_label', 'crypto_extra_time', 'crypto_description_2', 'crypto_overwrite_space'] self.check_visible_object_with_label(items) crypto_page.enter_crypto_phrase(crypto_password) self._check_page_titles() self._check_navigation_buttons() def custom_partition_page_tests(self, part_config=None): """ Runs the tests for the custom partition page The custom partition configurations are in partconfig.py. This function selects a random Config for each test run from partconfig.py. When adding a new config, import it and add it to the custom_configs list :param part_config: """ part_config = Config1 self._update_current_step('stepPartAdvanced') self._check_navigation_buttons() self._update_page_titles() logger.debug("run_custom_partition_page_tests()") logger.debug("Selecting the stepPartAdvanced page object") custom_page = self.main_window.select_single( 'GtkAlignment', BuilderName='stepPartAdvanced') treeview = custom_page.select_single('GtkTreeView') self.expectThat(treeview.visible, Equals(True), "[Page:'{0}'] Partition tree view was not visible") obj_list = ['partition_button_new', 'partition_button_delete', 'partition_button_edit', 'partition_button_edit', 'partition_button_new_label'] for name in obj_list: obj = custom_page.select_single(BuilderName=name) self.expectThat(obj.visible, Equals(True), "[Page:'{0}'] {1} object was not visible" .format(self.current_step, obj.name)) logger.debug("Sleeping while we wait for all UI elements to fully " "load") time.sleep(5) # need to give time for all UI elements to load custom_page.create_new_partition_table() #update number of table rows self.part_table_rows = treeview.get_number_of_rows() logger.debug("TOTAL NUMBER OF ROWS: {0}".format(self.part_table_rows)) #lets create the partitions from here if part_config: logger.debug("Setting the given partition config") config = part_config else: logger.debug("Selecting a random partition config") config = random.choice(custom_configs) logger.debug("LENGTH OF CONFIG IS: {0}".format(len(config))) logger.debug( "TOTAL NUMBER OF PARTITIONS IN CONFIG: {0}".format(len(config)) ) self.total_number_partitions = len(config) logger.debug( "TOTAL NUMBER OF PARTITIONS TO BE IN TABLE: {0}".format( self.total_number_partitions) ) for elem in config: self._add_new_partition() partition_dialog = self.main_window.get_dialog( 'GtkDialog', BuilderName='partition_dialog') self.assertThat(partition_dialog.visible, Eventually(Equals(True)), "Partition dialog not visible") partition_dialog.set_partition_size(elem['PartitionSize']) partition_dialog.set_partition_location(elem['Position']) partition_dialog.set_partition_type(elem['PartitionType']) partition_dialog.set_file_system_type(elem['FileSystemType']) partition_dialog.set_mount_point(elem['MountPoint']) ok_button = partition_dialog.select_single( 'GtkButton', BuilderName='partition_dialog_okbutton') self.pointing_device.click_object(ok_button) self.assertThat(partition_dialog.visible, Eventually(Equals(False)), "Partition dialog did not close") self._check_partition_created(elem) # TODO: Uncomment once bug 1066152 is fixed #self._check_page_titles() self._check_navigation_buttons() def location_page_tests(self, ): """ Runs the test for the Location page Due to not being able to introspect the timezone map we only have a choice of 4 locations which get selected at random. """ logger.debug('run_location_page_tests()') self._update_current_step('stepLocation') self._check_navigation_buttons(continue_button=True, back_button=True, quit_button=False, skip_button=False) self._update_page_titles() logger.debug("Selecting stepLocation page object") location_page = self.main_window.select_single( 'GtkBox', BuilderName='stepLocation') location_map = location_page.select_single('CcTimezoneMap') self.assertThat(location_map.visible, Equals(True), "Expected location map to be visible but it wasn't") location_entry = location_page.select_single( BuilderName='timezone_city_entry') self.assertThat(location_entry.visible, Equals(True), "Expected location entry to be visible but it wasn't") location = ['London', 'Paris', 'Madrid', 'Algiers'] if self.english_install: location_page.select_location('London') else: location_page.select_location(random.choice(location)) self._check_page_titles() self._check_navigation_buttons(continue_button=True, back_button=True, quit_button=False, skip_button=False) def keyboard_layout_page_tests(self, ): self._update_current_step('stepKeyboardConf') self._check_navigation_buttons(continue_button=True, back_button=True, quit_button=False, skip_button=False) self._update_page_titles() logger.debug("run_keyboard_layout_page_tests()") logger.debug("Selecting the stepKeyboardCOnf page object") keyboard_page = self.main_window.select_single( 'GtkAlignment', BuilderName='stepKeyboardConf') treeviews = keyboard_page.select_many('GtkTreeView') # lets check all the keyboard tree items for the selected language # TODO: we should probably test at some point try changing the keyboard # layout to a different language/locale/layout and see if # ubiquity breaks for treeview in treeviews: items = treeview.get_all_items() for item in items: self.expectIsInstance(item.accessible_name, str, "[Page:'%r'] Expected %r item to be " "unicode but it wasn't" % ( self.current_step, item.accessible_name)) self.expectThat(item.accessible_name, NotEquals(u''), "[Page:'{0}'] Tree view item found which " "didn't contain text, but it should!!") # now lets test typing with the keyboard layout entry = keyboard_page.select_single('GtkEntry') while True: text = u'Testing keyboard layout' with self.keyboard.focused_type(entry) as kb: kb.type(text) #check entry value is same length as text if len(entry.text) == len(text): # only test the entry value if we are using english install if self.english_install: self.expectThat(entry.text, Equals(text)) self.expectThat( entry.text, NotEquals(u''), "[Page:'{0}'] Expected Entry to contain text " "after typing but it didn't" .format(self.current_step)) self.expectIsInstance( entry.text, str, "[Page:'{0}'] Expected Entry text to be " "unicode but it wasnt" .format(self.current_step)) break #delete the entered text before trying again kb.press_and_release('Ctrl+a') kb.press_and_release('Delete') # TODO: Test detecting keyboard layout self._check_page_titles() self._check_navigation_buttons(continue_button=True, back_button=True, quit_button=False, skip_button=False) def user_info_page_tests(self, username, pwd, encrypted=False, autologin=False): """ Runs tests for the User Info Page :param username:*String*, name of user :param pwd: *String*, password for user :param encrypted: *Bool* if true encypts the home directory :param autologin: *Bool* if true sets the user account to login automagically """ self._update_current_step('stepUserInfo') self._check_navigation_buttons(continue_button=True, back_button=True, quit_button=False, skip_button=False) self._update_page_titles() logger.debug("Selecting stepUserInfo page") user_info_page = self.main_window.select_single( 'GtkBox', BuilderName='stepUserInfo') objects = ['hostname_label', 'username_label', 'password_label', 'verified_password_label', 'hostname_extra_label' ] logger.debug("checking user info page objects ......") self.check_visible_object_with_label(objects) user_info_page.create_user(username, pwd) #TODO: get these working if encrypted: user_info_page.encrypt_home_dir(encrypt=True) if autologin: user_info_page.set_auto_login() self._check_page_titles() self._check_navigation_buttons(continue_button=True, back_button=True, quit_button=False, skip_button=False) def progress_page_tests(self, ): ''' Runs the test for the installation progress page This method tracks the current progress of the install by using the fraction property of the progress bar to assertain the percentage complete. ''' #TODO: Remove all these prints once dbus bug is fixed logger.debug("run_install_progress_page_tests()") print("run_install_progress_page_tests()") #We cant assert page title here as its an external html page #Maybe try assert WebKitWebView is visible # # NOTE: disable test to check if webkit view is visible. autopilot # randomly crashes with LP#1284671 and very often in the QA Lab #print("Selecting WebKit") #webkitwindow = self.main_window.select_single( # 'GtkScrolledWindow', name='webkit_scrolled_window' #) #print("Test webkitwindow visible") #self.expectThat(webkitwindow.visible, Equals(True)) #print("Webkit window found and is visible") print("Selecting Progress bar") progress_bar = self.main_window.select_single('GtkProgressBar', name='install_progress') #Copying files progress bar print("Entering first tracking loop all that will be called " "from here is GtkWindow name = liveinstaller and the " "progressbar") self._track_install_progress() print("First loop complete waiting for pbar to go back to 0") self.assertThat(progress_bar.fraction, Eventually( Equals(0.0), timeout=180)) print("Now entering the second loop...........") #And now the install progress bar self._track_install_progress() def check_visible_object_with_label(self, visible_obj): """Check an visible objects label and visible properties, :param visible_obj: Accepts either a objects name property or a list of names ..note:: If english installation this function will also test the english label value which is retrieved from the generated english_config.ini file """ if isinstance(visible_obj, list): for item in visible_obj: self._check_object(item) return if isinstance(visible_obj, str): self._check_object(visible_obj) return raise ValueError( "Object name must either be a string or list of strings") def check_hidden_object_with_label(self, hidden_obj): """Check an hidden objects label and visible properties, :param hidden_obj: Accepts either a objects name property or a list of names """ if isinstance(hidden_obj, list): for item in hidden_obj: self._check_object(item, False) return if isinstance(hidden_obj, str): self._check_object(hidden_obj, False) return raise ValueError( "Object name must either be a string or list of strings") def _check_object(self, obj_name, obj_visible=True): logger.debug("Checking {0} object.......".format(obj_name)) #select current page object page = self.main_window.select_single(BuilderName=self.current_step) #select object page_object = page.select_single(BuilderName=obj_name) if obj_visible: visible_message = "[Page:'{0}'] Expected {1} object to be " \ "visible but it wasn't".format(self.current_step, page_object.name) else: visible_message = "[Page:'{0}'] Expected {1} object to not be " \ "visible but it was!".format(self.current_step, page_object.name) self.expectThat(page_object.visible, Equals(obj_visible), visible_message) self.expectThat(page_object.label, NotEquals(u''), "[Page:'{0}'] Expected {1} objects label value to " "contain text but it didn't" .format(self.current_step, page_object.name)) self.expectIsInstance(page_object.label, str, "[Page:'{0}'] Expected {1} objects label " "value to be unicode but it wasn't" .format(self.current_step, page_object.name)) #we only want to test visible english values, hidden ones don't matter if (self.current_step in self.english_config) and obj_visible: if self.english_install and ( obj_name in self.english_config[self.current_step]): logger.debug( "Checking {0} object's english label value....".format( obj_name)) #if english install check english values self.expectThat(page_object.label, Equals( self.english_config[self.current_step][obj_name])) def _track_install_progress(self, ): '''Gets the value of the fraction property of the progress bar so we can see when the progress bar is complete ''' logger.debug("_track_install_progress_bar()") print("_track_install_progress()") print("selecting progress bar") progress_bar = self.main_window.select_single('GtkProgressBar', name='install_progress') progress = 0.0 while progress < 1.0: #print("Progressbar = %d" % progress) #keep updating fraction value #print("Getting an updated pbar.fraction") progress = progress_bar.fraction #print("Got an updated pbar fraction") # lets sleep for longer at early stages then # reduce nearer to complete if progress < 0.5: time.sleep(5) elif progress < 0.7: time.sleep(3) elif progress < 0.85: time.sleep(1) else: pass #logger.debug('Percentage complete "{0:.0f}%"' # .format(progress * 100)) def _check_no_visible_dialogs(self, arg=None): # lets try grab some dialogs we know of dialogs = ['warning_dialog', 'crash_dialog', 'bootloader_fail_dialog', 'ubi_question_dialog'] safe_dialogs = ['finished_dialog', 'partition_dialog'] for dialog_name in dialogs: dialog = self.app.select_single(BuilderName=dialog_name) if dialog.visible: msg = self._get_dialog_message(dialog) # each dialog will display a label explaining the error self.expectNotVisible(dialog.visible, "{0} was found to be visible. " "With error message: \n" "{1}" .format(dialog.name, msg)) # Try grab dialogs created at runtime unknown_dialogs = self.app.select_many('GtkDialog') for dlg in unknown_dialogs: if dlg.name in dialogs or safe_dialogs: pass else: if dlg.visible: msg = self._get_dialog_message(dlg) # each dialog will display a label explaining the error self.expectNotVisible(dlg.visible, "Error dialog found to be visible " "With error message: \n" "{0}" .format(msg)) # Lets try and grab any spawned GtkMessageDialogs try: unknown_msg_dialogs = self.app.select_many('GtkMessageDialog') for dlg in unknown_msg_dialogs: msg = self._get_dialog_message(dlg) # each dialog will display a label explaining the error self.expectNotVisible(dlg.visible, "A GtkMessageDialog was found to be " "visible. With error message: \n" "{0}" .format(msg)) except StateNotFoundError: # catch statenotfound so we can continue pass def _get_dialog_message(self, dlg_object): dialog_labels = dlg_object.select_many('GtkLabel') message = '' for gtklabel in dialog_labels: #only add labels longer than 'Continue' so we avoid button labels if len(gtklabel.label) > 8: message += (gtklabel.label + '. ') return message def _add_new_partition(self, ): """ adds a new partition """ logger.debug("_add_new_partition()") custom_page = self.main_window.select_single( 'GtkAlignment', BuilderName='stepPartAdvanced') tree_view = custom_page.select_single('GtkTreeView') item = tree_view.select_item(u' free space') self.pointing_device.click_object(item) self.assertThat(item.selected, Equals(True), "[Page:'{0}'] Free Space tree item not selected" .format(self.current_step)) add_button = custom_page.select_single( 'GtkToolButton', BuilderName='partition_button_new') self.pointing_device.click_object(add_button) time.sleep(2) logger.debug('_add_new_partition complete') def _check_partition_created(self, config): """ Checks that the partition was created properly """ logger.debug("Checking partition was created.....") custom_page = self.main_window.select_single( 'GtkAlignment', BuilderName='stepPartAdvanced') tree_view = custom_page.select_single('GtkTreeView') #assert a new row has been added to the partition table total_rows = self._update_table_row_count(config) logger.debug("TOTAL NUMBER OF ROWS: {0}".format(self.part_table_rows)) self.assertThat(total_rows, Equals(self.part_table_rows)) items = tree_view.get_all_items() fsFormat = config['FileSystemType'] mount_point = config['MountPoint'] size_obj = config['PartitionSize'] if mount_point: index = next((index for index, value in enumerate(items) if mount_point == value.accessible_name), None) self.assertIsNotNone(index, "Could not get index for '{0}' tree item" .format(mount_point)) logger.debug("Found index for {0} tree item".format(mount_point)) fs_item = tree_view.select_item_by_index(index - 1) mount_item = tree_view.select_item_by_index(index) size_item = tree_view.select_item_by_index(index + 1) else: index = next((index for index, value in enumerate(items) if fsFormat.lower() == value.accessible_name), None) self.assertIsNotNone(index, "Could not get index for {0} FS tree item" .format(fsFormat)) logger.debug("Found index for {0} tree item".format(fsFormat)) fs_item = tree_view.select_item_by_index(index) mount_item = tree_view.select_item_by_index(index + 1) size_item = tree_view.select_item_by_index(index + 2) self.expectThat(fsFormat.lower(), Equals(fs_item.accessible_name)) self.expectThat(fs_item.visible, Equals(True), "[Page: '{0}'] Expected {0} to be visible but " "it wasn't".format(fs_item.accessible_name)) if mount_point: # Fail the test if we don't have correct mount point self.assertThat(mount_point, Equals(mount_item.accessible_name)) self.expectThat(mount_item.visible, Equals(True), "[Page: '{0}'] Expected {0} to be visible but " "it wasn't".format(mount_item.accessible_name)) if size_obj: self.expectThat( int(size_item.accessible_name.strip(' MB')), InRange((size_obj - 3), (size_obj + 3)), "[Page:'{0}'] Expected partition size to be " "somwhere in the range of {1}-{2}MB but instead was {3}. " "This means the created partition was significantly " "different in size to the requested amount of {4}MB" .format(self.current_step, str(size_obj - 3), str(size_obj + 3), size_item.accessible_name, str(size_obj))) self.expectThat(size_item.visible, Equals(True), "[Page: '{0}'] Expected {0} to be visible but " " it wasn't".format(size_item.accessible_name)) logger.debug("Partition created") def _check_navigation_buttons(self, continue_button=True, back_button=True, quit_button=True, skip_button=False): """ Function that checks the navigation buttons through out the install :param continue_button: Boolean value of buttons expected visibility :param back_button: Boolean value of buttons expected visibility :param quit_button: Boolean value of buttons expected visibility :param skip_button: Boolean value of buttons expected visibility """ logger.debug("check_window_constants({0}, {1}, {2}, {3})".format( continue_button, back_button, quit_button, skip_button)) con_button = self.main_window.select_single('GtkButton', name='next') self.assertThat(con_button.visible, Equals(continue_button)) bk_button = self.main_window.select_single('GtkButton', name='back') self.assertThat(bk_button.visible, Equals(back_button)) qt_button = self.main_window.select_single('GtkButton', name='quit') self.assertThat(qt_button.visible, Equals(quit_button)) skp_button = self.main_window.select_single('GtkButton', name='skip') self.assertThat(skp_button.visible, Equals(skip_button)) def _update_current_step(self, name): logger.debug("Updating current step to %s" % name) self.step_before = self.current_step self.current_step = name # Lets print current step print("Current step = {0}".format(self.current_step)) def _update_table_row_count(self, config): " Returns number of rows in table" custom_page = self.main_window.select_single( 'GtkAlignment', BuilderName='stepPartAdvanced') tree_view = custom_page.select_single('GtkTreeView') num = tree_view.get_number_of_rows() if num == self.total_number_partitions: #TODO: assert 'free space' changes to a partition # this will take some further work. time.sleep(15) return num if num == self.part_table_rows: timeout = 30 while True: if num is not self.part_table_rows + 1: time.sleep(1) num = tree_view.get_number_of_rows() if num is self.part_table_rows + 1: break elif not timeout: raise ValueError("No new rows in partition table") else: timeout -= 1 self.assertThat(num, Equals(self.part_table_rows + 1)) self.part_table_rows = num return num def _update_page_titles(self, ): self.previous_page_title = self.current_page_title self.current_page_title = self.main_window.select_single( 'GtkLabel', BuilderName='page_title').label def _check_page_titles(self, ): current_page_title = self.main_window.select_single( 'GtkLabel', BuilderName='page_title') if self.current_step in self.english_config: if self.english_install and ( 'page_title' in self.english_config[self.current_step]): #if english install check english values self.expectThat(current_page_title.label, Equals( self.english_config[self.current_step]['page_title'])) #also lets check it changed from the previous page message_one = "Expected %s page title '%s' to not equal the "\ "previous %s page title '%s' but it does" % ( self.current_step, self.current_page_title, self.step_before, self.previous_page_title) self.expectThat(self.previous_page_title, NotEquals(self.current_page_title), message=message_one) ## XXX Re-enable to catch bugs where page title changes after a page ## has loaded # ## This second one catches the known bug for the stepPartAdvanced page ## title switching back to the prev page title #message_two = "Expected %s page title '%s' to not equal the "\ # "previous %s page title '%s' but it does" % ( # self.current_step, current_page_title.label, # self.step_before, self.previous_page_title) ## This only runs if the current page title changes from its initial ## value when page loaded #if current_page_title.label != self.current_page_title: # self.expectThat(self.previous_page_title, # NotEquals(current_page_title.label), # message=message_two) # self.expectThat(current_page_title.visible, Equals(True), # "[Page:'{0}'] Expect page title to be visible " # "but it wasn't".format(self.current_step)) def _check_preparing_statebox(self, stateboxName, visible=True, imagestock='gtk-yes'): """ Checks the preparing page statebox's """ logger.debug("Running checks on {0} StateBox".format(stateboxName)) preparing_page = self.main_window.select_single( 'GtkAlignment', BuilderName='stepPrepare') state_box = preparing_page.select_single( 'StateBox', BuilderName=stateboxName) logger.debug('check({0}, {1})'.format(visible, imagestock)) logger.debug("Running checks.......") if visible: self.expectThat(state_box.visible, Equals(visible), "StateBox.check(): Expected {0} statebox to be " "visible but it wasn't" .format(state_box.name)) label = state_box.select_single('GtkLabel') self.expectThat(label.label, NotEquals(u''), "[Page:'{0}'] Expected {1} Statebox's label to " "contain text but it didn't" .format(self.current_step, stateboxName)) self.expectThat(label.visible, Equals(visible), "[Page:'{0}'] Expected {1} Statebox label's " "visible property to be {2} " .format(self.current_step, stateboxName, str(visible))) self.expectIsInstance(label.label, str, "[Page:'{0}'] Expected {1} Statebox's label " "to be unicode but it wasn't" .format(self.current_step, stateboxName)) image = state_box.select_single('GtkImage') self.expectThat(image.stock, Equals(imagestock)) self.expectThat(image.visible, Equals(visible)) else: self.expectThat(state_box.visible, Equals(False), "[Page:'{0}'] Expected {1} statebox to not be " "visible but it was" .format(self.current_step, stateboxName)) def get_distribution(self, ): """Returns the name of the running distribution.""" logger.debug("Detecting flavor") with open('/cdrom/.disk/info') as f: for line in f: distro = line[:max(line.find(' '), 0) or None] if distro: logger.debug("{0} flavor detected".format(distro)) return str(distro) raise SystemError("Could not get distro name")
class GtkBox(GtkContainers): """ Emulator class for a GtkBox instance """ def __init__(self, *args): super(GtkBox, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() def get_random_language(self, ): """ gets a random language from the 'stepLanguage' page :returns: A random TreeView item from the language treeview :raises: EmulatorException if function is not called from the step language page object You can now use select_language_item """ logger.debug("get_random_language()") if self.name == 'stepLanguage': language_item = self._get_install_language() if language_item is None: raise ValueError("Language could not be selected") return language_item raise RuntimeError("Function can only be used from a stepLanguage " "page object. Use .select_single('GtkBox, " "name='stepLanguage')") def select_language(self, item): """ Selects a language for the install You can either use get_random_language or if you want to set the install language instead of randomly selecting an item. Then select from the treeview using GtkTreeView.select_item and pass the returned item to select_language :param item: A treeview item object :raises: exception if function not called from stepLanguage page object """ if self.name == 'stepLanguage': logger.debug("select_language()") treeview = self.select_single('GtkTreeView') treeview.click() #for sanity lets ensure we always start at the top of the list logger.debug("Selecting top item of treeview list") self.kbd.press_and_release('Home') tree_items = treeview.get_all_items() top_item = tree_items[0] #If we are at the top if top_item.selected: logger.debug("top item {0} selected" .format(top_item.accessible_name)) #Now select required Language self.kbd.type(item.accessible_name[0:2]) item.click() #check selected if item.selected: logger.debug("Install language successfully selected! :-)") return raise ValueError("Could not select Item") raise ValueError("Top item not selected") raise ValueError("Function can only be used from a stepLanguage page " "object. Use .select_single('GtkBox, " "name='stepLanguage')") def _get_install_language(self, ): """ Gets a random language for the install :returns: an object of a TreeView item for the chosen language """ logger.debug("_get_install_language()") treeview = self.select_single('GtkTreeView') #lets get all items treeview_items = treeview.get_all_items() #get a language which the first two chars can be ascii decoded test_language = self._get_decode_ascii_item(treeview_items) return test_language def _get_decode_ascii_item(self, items): """ decodes a list of unicode items """ logger.debug("_get_decode_ascii_item()") # at the moment we can't select all locales as this would be a pain # to figure out all encodings for keyboard input lang_item = None l_ascii = None while True: lang_item = random.choice(items) l_unicode = lang_item.accessible_name logger.debug("Attempting to decode %s" % l_unicode) lan = l_unicode[0:2] try: l_ascii = lan.encode('ascii') except UnicodeEncodeError: logger.debug("%s could not be decoded" % l_unicode) pass if l_ascii: logger.debug("%s decoded successfully" % l_unicode) break logger.debug("Returning selected language: %s" % l_unicode) return lang_item def select_location(self, location): """ Selects a location on the timezone map """ if self.name == 'stepLocation': logger.debug("select_location({0})".format(location)) location_map = self.select_single('CcTimezoneMap') self.pointing_device.move_to_object(location_map) x1, y1, x2, y2 = location_map.globalRect #hmmmm this is tricky! and really hacky pos = self.pointing_device.position() x = pos[0] y = pos[1] x -= 25 # px self.pointing_device.move(x, y) while True: entry = self.select_single('GtkEntry') if entry.text != location: pos = self.pointing_device.position() x = pos[0] y = pos[1] y -= 10 # px self.pointing_device.move(x, y) self.pointing_device.click() if y < y1: logger.warning("We missed the location on the map and " "ended up outside the globalRect. Now " "using the default selected location " "instead") break else: expectThat(entry.text).equals(location) logger.debug("Location; '{0}' selected".format(location)) break else: raise ValueError("Function can only be called from a " "stepLocation page object") def create_user(self, name, password): """ Creates a user account with password :param name: Username :param password: user password """ logger.debug("create_user({0}, {1})".format(name, password)) if self.name == 'stepUserInfo': self._enter_username(name) self._enter_password(password) else: raise ValueError("Function can only be called froma stepUserInfo" "page object") def _enter_username(self, name): """ Enters the username :param name: username for user account """ logger.debug("_enter_username({0})".format(name)) entry = self.select_single('GtkEntry', name='fullname') with self.kbd.focused_type(entry) as kb: kb.press_and_release('Ctrl+a') kb.press_and_release('Delete') kb.type(name) #lets get the fullname from the entry # as we don't know the kb layout till runtime fullname = entry.text logger.debug("Checking that name, username and hostname all contain " "'{0}'".format(name)) #now check computer name contains username hostname_entry = self.select_single('GtkEntry', name='hostname') expectThat(hostname_entry.text).contains( fullname.lower(), msg="GtkBox._enter_username(): Expected the hostname entry: " "'{0}', to contain '{1}'" .format(hostname_entry.text, fullname.lower())) #check username contains name username_entry = self.select_single('GtkEntry', name='username') expectThat(username_entry.text).contains( fullname.lower(), msg="GtkBox._enter_username(): Expected the username entry: " "'{0}', to contain '{1}'" .format(username_entry.text, fullname.lower())) #check the GtkYes images are now visible logger.debug("Checking the stock 'gtk-yes' images are visible") images = ['fullname_ok', 'hostname_ok', 'username_ok'] for image in images: img = self.select_single('GtkImage', name=image) expectThat(img.visible).equals( True, msg="Expected {0} image to be visible but it wasn't" .format(img.name)) expectThat(img.stock).equals( 'gtk-yes', msg="Expected {0} image to have a 'gtk-yes' stock image and " "not {1}".format(img.name, img.stock)) def _enter_password(self, password): if self.name == 'stepUserInfo': while True: self._enter_pass_phrase(password) match = self._check_phrase_match() if match: break else: raise ValueError("enter_crypto_phrase() can only be called from " "stepPartCrypto page object") def _enter_pass_phrase(self, phrase): pwd_entries = ['password', 'verified_password'] for i in pwd_entries: entry = self.select_single(BuilderName=i) with self.kbd.focused_type(entry) as kb: kb.press_and_release('Ctrl+a') kb.press_and_release('Delete') expectThat(entry.text).equals( u'', msg='{0} entry text was not cleared properly' .format(entry.name)) kb.type(phrase) def _check_phrase_match(self, ): pwd1 = self.select_single(BuilderName='password').text pwd2 = self.select_single(BuilderName='verified_password').text if pwd1 == pwd2: return True else: return False def encrypt_home_dir(self, encrypt=None): """ Check the login_encrypt box """ chk_encrypt = self.select_single(BuilderName='login_encrypt') active = chk_encrypt.active if encrypt is None: # Switch checkbox and ensure it switched self.pointing_device.click_object(chk_encrypt) expectThat(chk_encrypt.active).equals( not active, msg='encrypt home checkbox state did not change. Current ' 'state: {0}'.format(chk_encrypt.active)) elif encrypt and not active: self.pointing_device.click_object(chk_encrypt) expectThat(chk_encrypt.active).equals( True, msg='encrypt home checkbox not active and should be.') elif not encrypt and active: self.pointing_device.click_object(chk_encrypt) expectThat(chk_encrypt.active).equals( False, msg='encrypt home checkbox active and should not be.') else: raise ValueError("Invalid value for 'encrypt' parameter: {}" .format(encrypt))
class GtkBox(GtkContainers): """ Emulator class for a GtkBox instance """ def __init__(self, *args): super(GtkBox, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() def get_random_language(self, ): """ gets a random language from the 'stepLanguage' page :returns: A random TreeView item from the language treeview :raises: EmulatorException if function is not called from the step language page object You can now use select_language_item """ logger.debug("get_random_language()") if self.name == 'stepLanguage': language_item = self._get_install_language() if language_item is None: raise ValueError("Language could not be selected") return language_item raise RuntimeError("Function can only be used from a stepLanguage " "page object. Use .select_single('GtkBox, " "name='stepLanguage')") def select_language(self, item): """ Selects a language for the install You can either use get_random_language or if you want to set the install language instead of randomly selecting an item. Then select from the treeview using GtkTreeView.select_item and pass the returned item to select_language :param item: A treeview item object :raises: exception if function not called from stepLanguage page object """ if self.name == 'stepLanguage': logger.debug("select_language()") treeview = self.select_single('GtkTreeView') treeview.click() # for sanity lets ensure we always start at the top of the list logger.debug("Selecting top item of treeview list") self.kbd.press_and_release('Home') tree_items = treeview.get_all_items() top_item = tree_items[0] # If we are at the top if top_item.selected: logger.debug("top item {0} selected".format( top_item.accessible_name)) # Now select required Language self.kbd.type(item.accessible_name[0:2]) item.click() # check selected if item.selected: logger.debug("Install language successfully selected! :-)") return raise ValueError("Could not select Item") raise ValueError("Top item not selected") raise ValueError("Function can only be used from a stepLanguage page " "object. Use .select_single('GtkBox, " "name='stepLanguage')") def _get_install_language(self, ): """ Gets a random language for the install :returns: an object of a TreeView item for the chosen language """ logger.debug("_get_install_language()") treeview = self.select_single('GtkTreeView') # lets get all items treeview_items = treeview.get_all_items() # get a language which the first two chars can be ascii decoded test_language = self._get_decode_ascii_item(treeview_items) return test_language def _get_decode_ascii_item(self, items): """ decodes a list of unicode items """ logger.debug("_get_decode_ascii_item()") # at the moment we can't select all locales as this would be a pain # to figure out all encodings for keyboard input lang_item = None l_ascii = None while True: lang_item = random.choice(items) l_unicode = lang_item.accessible_name logger.debug("Attempting to decode %s" % l_unicode) lan = l_unicode[0:2] try: l_ascii = lan.encode('ascii') except UnicodeEncodeError: logger.debug("%s could not be decoded" % l_unicode) pass if l_ascii: logger.debug("%s decoded successfully" % l_unicode) break logger.debug("Returning selected language: %s" % l_unicode) return lang_item def select_location(self, location): """ Selects a location on the timezone map """ if self.name == 'stepLocation': logger.debug("select_location({0})".format(location)) location_map = self.select_single('CcTimezoneMap') self.pointing_device.move_to_object(location_map) x1, y1, x2, y2 = location_map.globalRect # hmmmm this is tricky! and really hacky pos = self.pointing_device.position() x = pos[0] y = pos[1] x -= 25 # px self.pointing_device.move(x, y) while True: entry = self.select_single('GtkEntry') if entry.text != location: pos = self.pointing_device.position() x = pos[0] y = pos[1] y -= 10 # px self.pointing_device.move(x, y) self.pointing_device.click() if y < y1: logger.warning("We missed the location on the map and " "ended up outside the globalRect. Now " "using the default selected location " "instead") break else: expectThat(entry.text).equals(location) logger.debug("Location; '{0}' selected".format(location)) break else: raise ValueError("Function can only be called from a " "stepLocation page object") def create_user(self, name, password): """ Creates a user account with password :param name: Username :param password: user password """ logger.debug("create_user({0}, {1})".format(name, password)) if self.name == 'stepUserInfo': self._enter_username(name) self._enter_password(password) else: raise ValueError("Function can only be called froma stepUserInfo" "page object") def _enter_username(self, name): """ Enters the username :param name: username for user account """ logger.debug("_enter_username({0})".format(name)) entry = self.select_single('GtkEntry', name='fullname') with self.kbd.focused_type(entry) as kb: kb.press_and_release('Ctrl+a') kb.press_and_release('Delete') kb.type(name) # lets get the fullname from the entry # as we don't know the kb layout till runtime fullname = entry.text logger.debug("Checking that name, username and hostname all contain " "'{0}'".format(name)) # now check computer name contains username hostname_entry = self.select_single('GtkEntry', name='hostname') expectThat(hostname_entry.text).contains( fullname.lower(), msg="GtkBox._enter_username(): Expected the hostname entry: " "'{0}', to contain '{1}'".format(hostname_entry.text, fullname.lower())) # check username contains name username_entry = self.select_single('GtkEntry', name='username') expectThat(username_entry.text).contains( fullname.lower(), msg="GtkBox._enter_username(): Expected the username entry: " "'{0}', to contain '{1}'".format(username_entry.text, fullname.lower())) # check the GtkYes images are now visible logger.debug("Checking the stock 'gtk-yes' images are visible") images = ['fullname_ok', 'hostname_ok', 'username_ok'] for image in images: img = self.select_single('GtkImage', name=image) expectThat(img.visible).equals( True, msg="Expected {0} image to be visible but it wasn't".format( img.name)) expectThat(img.stock).equals( 'gtk-yes', msg="Expected {0} image to have a 'gtk-yes' stock image and " "not {1}".format(img.name, img.stock)) def _enter_password(self, password): if self.name == 'stepUserInfo': while True: self._enter_pass_phrase(password) match = self._check_phrase_match() if match: break else: raise ValueError("enter_crypto_phrase() can only be called from " "stepPartCrypto page object") def _enter_pass_phrase(self, phrase): pwd_entries = ['password', 'verified_password'] for i in pwd_entries: entry = self.select_single(BuilderName=i) with self.kbd.focused_type(entry) as kb: kb.press_and_release('Ctrl+a') kb.press_and_release('Delete') expectThat(entry.text).equals( u'', msg='{0} entry text was not cleared properly'.format( entry.name)) kb.type(phrase) def _check_phrase_match(self, ): pwd1 = self.select_single(BuilderName='password').text pwd2 = self.select_single(BuilderName='verified_password').text if pwd1 == pwd2: return True else: return False def encrypt_home_dir(self, encrypt=None): """ Check the login_encrypt box """ chk_encrypt = self.select_single(BuilderName='login_encrypt') active = chk_encrypt.active if encrypt is None: # Switch checkbox and ensure it switched self.pointing_device.click_object(chk_encrypt) expectThat(chk_encrypt.active).equals( not active, msg='encrypt home checkbox state did not change. Current ' 'state: {0}'.format(chk_encrypt.active)) elif encrypt and not active: self.pointing_device.click_object(chk_encrypt) expectThat(chk_encrypt.active).equals( True, msg='encrypt home checkbox not active and should be.') elif not encrypt and active: self.pointing_device.click_object(chk_encrypt) expectThat(chk_encrypt.active).equals( False, msg='encrypt home checkbox active and should not be.') else: raise ValueError( "Invalid value for 'encrypt' parameter: {}".format(encrypt))
class UbuntuKeyboardTests(AutopilotTestCase): maliit_override_file = os.path.expanduser( "~/.config/upstart/maliit-server.override" ) @classmethod def setUpClass(cls): try: logger.debug("Creating the override file.") with open( UbuntuKeyboardTests.maliit_override_file, 'w' ) as override_file: override_file.write("exec maliit-server -testability") process_helpers.restart_unity_with_testability() _assertUnityReady() #### FIXME: This is a work around re: lp:1238417 #### if model() != "Desktop": from autopilot.input import _uinput _uinput._touch_device = _uinput.create_touch_device() #### #### FIXME: Workaround re: lp:1248902 and lp:1248913 logger.debug("Waiting for maliit-server to be ready") sleep(10) #### except IOError as e: e.args += ( "Failed attempting to write override file to {file}".format( file=UbuntuKeyboardTests.maliit_override_file ), ) raise @classmethod def tearDownClass(cls): try: os.remove(UbuntuKeyboardTests.maliit_override_file) except OSError: logger.warning("Attempted to remove non-existent override file") _restart_unity8() def setUp(self): if model() == "Desktop": self.skipTest("Ubuntu Keyboard tests only run on device.") super(UbuntuKeyboardTests, self).setUp() self.pointer = Pointer(Touch.create()) def launch_test_input_area(self, label="", input_hints=None): self.app = self._launch_simple_input(label, input_hints) text_area = self.app.select_single("QQuickTextInput") return text_area def ensure_focus_on_input(self, input_area): self.pointer.click_object(input_area) keyboard = Keyboard() self.addCleanup(keyboard.dismiss) self.assertThat(keyboard.is_available, Eventually(Equals(True))) def _start_qml_script(self, script_contents): """Launch a qml script.""" qml_path = tempfile.mktemp(suffix='.qml') open(qml_path, 'w').write(script_contents) self.addCleanup(os.remove, qml_path) desktop_file = self._write_test_desktop_file() return self.launch_test_application( base.get_qmlscene_launch_command(), qml_path, '--desktop_file_hint=%s' % desktop_file, app_type='qt', ) def _write_test_desktop_file(self): desktop_file_dir = self.get_local_desktop_file_directory() if not os.path.exists(desktop_file_dir): os.makedirs(desktop_file_dir) with tempfile.NamedTemporaryFile( suffix='.desktop', dir=desktop_file_dir, delete=False ) as desktop_file: desktop_file.write( "[Desktop Entry]\n" "Type=Application\n" "Exec=Not important\n" "Path=Not important\n" "Name=Test app\n" "Icon=Not important" ) self.addCleanup(os.remove, desktop_file.name) return desktop_file.name def get_local_desktop_file_directory(self): return os.path.join( os.getenv('HOME'), '.local', 'share', 'applications' ) def _launch_simple_input(self, label="", input_hints=None): if input_hints is None: extra_script = "Qt.ImhNoPredictiveText" else: extra_script = "|".join(input_hints) simple_script = dedent(""" import QtQuick 2.0 import Ubuntu.Components 0.1 Rectangle { id: window objectName: "windowRectangle" color: "lightgrey" Text { id: inputLabel text: "%(label)s" font.pixelSize: units.gu(3) anchors { left: input.left top: parent.top topMargin: 25 bottomMargin: 25 } } TextField { id: input; objectName: "input" anchors { top: inputLabel.bottom horizontalCenter: parent.horizontalCenter topMargin: 10 } inputMethodHints: %(input_method)s } } """ % {'label': label, 'input_method': extra_script}) return self._start_qml_script(simple_script)
class DejaDupTestCase(AutopilotTestCase): """A test case base class for the UI.""" def setUp(self): super(DejaDupTestCase, self).setUp() self.pointer = Pointer(Mouse.create()) self.rootdir = os.environ['DEJA_DUP_TEST_ROOT'] self.sourcedir = os.path.join(self.rootdir, 'source') self.copydir = os.path.join(self.rootdir, 'source.copy') self.backupdir = os.path.join(self.rootdir, 'backup') self.addCleanup(self.safe_rmtree, self.sourcedir) self.addCleanup(self.safe_rmtree, self.copydir) self.addCleanup(self.safe_rmtree, self.backupdir) self.addCleanup(self.safe_rmtree, os.path.join(self.rootdir, 'cache')) try: os.makedirs(self.sourcedir) except OSError: pass self.set_config("root-prompt", False) self.set_config("location-mode", "filename-entry", schema="org.gtk.Settings.FileChooser", path="/org/gtk/settings/file-chooser/") # And a catch-all for the other settings that get set as part of a # deja-dup run, like last-backup or such. self.addCleanup(os.system, "gsettings reset-recursively org.gnome.DejaDup") def safe_rmtree(self, folder): if os.path.exists(folder): shutil.rmtree(folder) def set_config(self, key, value, schema="org.gnome.DejaDup", path=None): settings = Gio.Settings(schema=schema, path=path) if type(value) is list: settings.set_strv(key, value) elif type(value) is bool: settings.set_boolean(key, value) elif type(value) is str: settings.set_string(key, value) else: settings.set_value(key, value) self.addCleanup(settings.reset, key) def iterate(self, p): "Not meant for production use, just a debugging tool" print(p, p.get_properties()) for c in p.get_children(): self.iterate(c) def point_at_data_playground(self): self.set_config("include-list", [self.sourcedir]) self.set_config("backend", "file") self.set_config("path", self.backupdir, schema="org.gnome.DejaDup.File") def add_simple_data(self): """Just put some really simple data in the backup source.""" with open(os.path.join(self.sourcedir, 'one'), 'w') as f: f.write('one') with open(os.path.join(self.sourcedir, 'two'), 'w') as f: f.write('two') with open(os.path.join(self.sourcedir, 'three'), 'w') as f: f.write('three') subdir = os.path.join(self.sourcedir, 'subdir') os.mkdir(subdir) with open(os.path.join(subdir, 'one'), 'w') as f: f.write('one') deeper = os.path.join(subdir, 'deeper') os.mkdir(deeper) def add_random_data(self, name, size): """Fill a file with random bytes, which are poorly compressable. Size is in megabytes.""" with open(os.path.join(self.sourcedir, name), 'wb') as f: for i in range(size): f.write(os.urandom(1024 * 1024)) def use_simple_setup(self): self.point_at_data_playground() self.add_simple_data() def header_string(self, label): return '<span size="xx-large" weight="ultrabold">%s</span>' % label def cancel(self, app): button = app.select_single('GtkLabel', label='_Cancel') self.pointer.click_object(button) self.assertThat(app.process.poll, Eventually(Equals(0))) def resume(self, app): button = app.select_single('GtkLabel', label='_Resume Later') self.pointer.click_object(button) self.assertThat(app.process.poll, Eventually(Equals(0))) def backup(self, gui=True, first=True, encrypted=True, waitfor=None): if not gui: # Sometimes we just want the backup to exist, without testing the # gui workflow itself. Note that this puts the archive files in # a place where deja-dup won't find them. Do we want that? p = subprocess.Popen([ 'env', 'PASSPHRASE=test', 'duplicity', '/', '--include=' + self.sourcedir, '--exclude=**', 'file://' + self.backupdir ], stdout=subprocess.PIPE) p.communicate() self.assertEqual(0, p.returncode) return None app = self.launch_test_application('deja-dup', '--backup') header = app.select_single('GtkLabel', name='header') entries = [] if first: header_label = self.header_string("Require Password?") self.assertThat(header.label, Eventually(Equals(header_label))) if encrypted: entries = app.select_many('GtkEntry', visible=True) self.assertEquals(len(entries), 2) for entry in entries: with self.keyboard.focused_type( entry, pointer=self.pointer) as kb: kb.type("test") else: radio_label = '_Allow restoring without a password' radio = app.select_single('GtkLabel', label=radio_label) self.pointer.click_object(radio) button = app.select_single('GtkLabel', label='Co_ntinue') self.pointer.click_object(button) elif encrypted: header_label = self.header_string("Encryption Password Needed") self.assertThat(header.label, Eventually(Equals(header_label))) entry = app.select_single('GtkEntry', visible=True) with self.keyboard.focused_type(entry, pointer=self.pointer) as kb: kb.type("test") button = app.select_single('GtkLabel', label='Co_ntinue') self.pointer.click_object(button) if waitfor is None: self.assertThat(app.process.poll, Eventually(Equals(0), timeout=30)) return None else: globstr = os.path.join(self.backupdir, waitfor) self.assertThat(lambda: glob.glob(globstr), Eventually(NotEquals([]), timeout=30)) return app def copy_sourcedir(self, delete=True): if delete: shutil.move(self.sourcedir, self.copydir) else: shutil.copytree(self.sourcedir, self.copydir, symlinks=True) def restore(self, encrypted=True, files=[]): app = self.launch_test_application('deja-dup', '--restore', *files) header = app.select_single('GtkLabel', name='header') button = app.select_single('GtkLabel', label='_Forward') self.pointer.click_object(button) self.assertThat( header.label, Eventually(Equals(self.header_string("Restore From When?")))) button = app.select_single('GtkLabel', label='_Forward') self.pointer.click_object(button) if not files: self.assertThat( header.label, Eventually(Equals(self.header_string("Restore to Where?")))) button = app.select_single('GtkLabel', label='_Forward') self.pointer.click_object(button) self.assertThat(header.label, Eventually(Equals(self.header_string("Summary")))) button = app.select_single('GtkLabel', label='_Restore') self.pointer.click_object(button) if encrypted: self.assertThat( header.label, Eventually(Equals( self.header_string("Encryption Password Needed")), timeout=30)) entry = app.select_single('GtkEntry', visible=True) with self.keyboard.focused_type(entry, pointer=self.pointer) as kb: kb.type("test") button = app.select_single('GtkLabel', label='Co_ntinue') self.pointer.click_object(button) self.assertThat( header.label, Eventually(Equals(self.header_string("Restore Finished")), timeout=30)) button = app.select_single('GtkLabel', label='_Close') self.pointer.click_object(button) def restore_missing(self, path, files): self.assertNotEqual(len(files), 0) app = self.launch_test_application('deja-dup', '--restore-missing', path) header = app.select_single('GtkLabel', name='header') button = app.select_single('GtkLabel', label='_Forward') self.pointer.click_object(button) self.assertThat( header.label, Eventually(Equals( self.header_string("Encryption Password Needed")), timeout=30)) entry = app.select_single('GtkEntry', visible=True) with self.keyboard.focused_type(entry, pointer=self.pointer) as kb: kb.type("test") button = app.select_single('GtkLabel', label='Co_ntinue') self.pointer.click_object(button) label = app.select_single('GtkLabel', BuilderName='status-label') self.assertThat(label.label, Eventually(Equals("Scanning finished"))) tree = app.select_single('GtkTreeViewAccessible') checkboxes = tree.select_many('GtkBooleanCellAccessible') labels = tree.select_many('GtkTextCellAccessible') for i in range(len(checkboxes)): # Multiply by two, because there are two labels for each checkbox. # The first is the name, the second is the date. if labels[i * 2].accessible_name in files: self.pointer.click_object(checkboxes[i]) button = app.select_single('GtkLabel', label='_Forward') self.pointer.click_object(button) self.assertThat(header.label, Eventually(Equals(self.header_string("Summary")))) button = app.select_single('GtkLabel', label='_Restore') self.pointer.click_object(button) self.assertThat( header.label, Eventually(Equals( self.header_string("Encryption Password Needed")), timeout=30)) # No need to enter text, it should be saved from before button = app.select_single('GtkLabel', label='Co_ntinue') self.pointer.click_object(button) self.assertThat( header.label, Eventually(Equals(self.header_string("Restore Finished")), timeout=300000)) button = app.select_single('GtkLabel', label='_Close') self.pointer.click_object(button) def compare(self, equal=None, missing=[]): if equal is None: self.assertEqual( 0, os.system('diff -ruN "%s" "%s"' % (self.copydir, self.sourcedir))) return for e in equal: copy = os.path.join(self.copydir, e) source = os.path.join(self.sourcedir, e) self.assertEqual(0, os.system('diff -ruN "%s" "%s"' % (copy, source))) for m in missing: source = os.path.join(self.sourcedir, m) self.assertEqual(False, os.path.exists(source))
class GtkComboBox(AutopilotGtkEmulatorBase): """ Emulator class for a GtComboBox instance""" def __init__(self, *args): super(GtkComboBox, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) self.kbd = Keyboard.create() def click(self, ): """Click Instance """ self.pointing_device.click_object(self) def select_item(self, labelText, enter=True): """ Selects an item in a GtkComboBox by its UI label text value :param labelText: The label value of the list item as seen on the UI :raises: **ValueError** when item is not in ComboBox list e.g. :: combobox = self.main_window.select_single('GtkComboBox') combobox.select_item('ListItem') If for some reason this doesn't work then use the :func:`click()` function to get the combobox focus """ logger.debug('Selecting "{0}" item'.format(labelText)) # get our gail combo to start combo = self._get_gail_combobox() # get total number of items in the combo items = combo.select_many('GtkMenuItemAccessible') self.click() # lets start at the top of the list self.kbd.press_and_release('Home') if enter: self.kbd.press_and_release('Enter') else: self.kbd.press_and_release('Down') # XXX: we should probably check the item is in the combo before # cycling through. for item in items: if labelText == combo.accessible_name: logger.debug('Item is now selected') return else: logger.debug('Go to next item in combo') self.kbd.press_and_release('Down') raise ValueError( 'Item with label text "{0}" was not found'.format(labelText)) def select_filesystem_format(self, fsFormat): logger.debug('Selecting "{0}" item'.format(fsFormat)) # get our gail combo to start combo = self._get_gail_combobox() # get total number of items in the combo items = combo.select_many('GtkMenuItemAccessible') self.click() # lets start at the top of the list self.kbd.press_and_release('Home') self.kbd.press_and_release('Enter') index = next((index for index, value in enumerate(items) if fsFormat == value.accessible_name), None) i = 0 while True: if i < index: self.kbd.press_and_release('Down') i += 1 else: assert i == index break def _get_gail_combobox(self, ): """ Gets the GtkComBox's corresponding GtkComboBoxAccessible object """ # lets get a root instance logger.debug('Getting corresponding GtkComboBoxAccessible object') root = self.get_root_instance() assert root is not None combos = root.select_many('GtkComboBoxAccessible', globalRect=self.globalRect) for combo in combos: if combo.visible: logger.debug('Combo found, returning combo') return combo raise ValueError( "No ComboBox visible with globalRect {0}".format(self.globalRect) )
class GtkTreeView(AutopilotGtkEmulatorBase): """ Emulator for a GtkTreeView instance """ def __init__(self, *args): super(GtkTreeView, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def click(self, ): """ This simply clicks a treeview object """ self.pointing_device.click_object(self) expectThat(self.is_focus).equals(True) def select_item(self, labelText): """ Selects an item in a GtkTreeView by its UI label text :param labelText: The label value of the tree item as seen on the UI :returns: An object of the requested treeitem e.g. If you want to click say an item displaying 'Home' in a treeview then it would be:: treeitem = treeview.select_item('Home') treeitem.click() If for some reason this doesn't work then use the :func:`click()` function to get the treeviews focus """ logger.debug('Selecting "{0}" item'.format(labelText)) try: # lets try and get the corresponding GailTreeView so we can assure # we are selecting the item from the correct treeview treeview = self._get_gail_treeview() treeview_item = treeview.select_item(str(labelText)) except ValueError: # lets catch the exception and have one last go at selecting the # item from a root instance # This may return more than one though. logger.warning('Could not get corresponding ' 'GtkTreeViewAccessibleObject with globalRect {0}. ' 'Trying to select GtkTreeView item from root ' 'object instead'.format(self.globalRect)) root = self.get_root_instance() if root is None: raise ValueError("Emulator could not get a root instance") treeview_item = root.select_single('GtkCellTextAccessible', accessible_name=str(labelText)) if treeview_item is None: raise ValueError( "Could not select item with label '{0}'".format(labelText)) logger.debug('Corresponding Item Found in treeview. Returning item.') return treeview_item def select_item_by_index(self, index): """ Selects an item in a GtkTreeVIew by its index :param index: index of the list item :rtype: Object of the treeview item at the selected index """ treeview = self._get_gail_treeview() treeview_item = treeview.select_item_by_index(index) if treeview_item is None: raise ValueError("Could not select item with index '{0}'" .format(index)) return treeview_item def get_all_items(self, startWith=None): logger.debug('GtkTreeView.get_all_items()') treeview = self._get_gail_treeview() items = treeview.get_all_items(startWith) if items is None: raise ValueError("NoneType: Could not get list of items") return items def get_partition_table_dict(self, ): """ Returns a dict of named tuples generated by the list of items returned from get_all_items. This enables us to access any available table cell using the Row number and column name example usage: >>> treeview = self.app.select_single('GtkTreeView') >>> table = treeview.get_partition_table_dict() # we can now access any cell using Row number as Key and column name i.e table['Row Number'].ColumnName >>> item = table['Row2'].Mount We now have an introspectable object for that particular cell which we can use to either assert the properties of the cell and also click etc.... >>> self.assertThat(item.accessible_name, Equals('/home')) >>> self.mouse.click(item) """ # first get accessible tree treeview = self._get_gail_treeview() # Now each column header is a GtkButton, so we get the label from each # one and create a list tree_column_objects = treeview.select_many('GtkButtonAccessible') column_names = [] for column in tree_column_objects: # We are only interested in columns with headers. Blank columns # seem to usually be used for spacing and contain no cells if column.accessible_name == '': pass else: # strip all non alpaha chars name = re.sub(r'\W+', '', column.accessible_name) column_names.append(name) # Create a named tuple using the column headers, which enables access # to the column by name Columns = namedtuple('Columns', column_names) # generate a list of items tree_items = treeview.get_all_items() # lets create a temp list temp_list = [] # TODO: we actually don't really need this for item in tree_items: temp_list.append(item) # so we want to create a Columns tuple for each row in the table # therefore picking only the n items where n is the number of column # names start, end = 0, len(column_names) row_list, table_dict = [], {} for i in range(0, int(len(temp_list) / len(column_names))): # fill columns tuple row = Columns(*temp_list[start:end]) # create a new tuple adding the current row number # which we will use as dict key row_list.append(('Row{0}'.format(i + 1), row)) # update our table dict table_dict.update(row_list) # remove the items we just added from the temp list del temp_list[start:end] # return table_dict return table_dict def get_number_of_rows(self, ): items = self.get_partition_table_dict() return len(items) def _get_gail_treeview(self, ): """ Gets the GtkTreeViews corresponding GtkTreeViewAccessible object """ logger.debug('Getting corresponding GtkTreeViewAccessible object') # As the treeview item is in the GAILWindow tree and not our current # tree We want to select the treeviewaccessible with the same # globalRect as us logger.debug('Selecting GtkTreeViewAccessible with same globalRect,\ or at least within close range') # if the treeviews are nested they could potentially have the # same globalRect so lets pick out the one thats visible for treeview in self._get_all_atktreeviews_within_range(): if treeview.visible: logger.debug('GtkTreeViewAccessible object found, ' 'returning object.') return treeview raise ValueError( "No treeview visible with globalRect {0}".format(self.globalRect) ) # So this is a workaround for the ATK treeviews globalrect # being slightly different compared to it's GtkTreeView counterpart. def _get_all_atktreeviews_within_range(self, ): # lets get a root instance root = self.get_root_instance() assert root is not None treeviews = [] # This is going to be slow! but what more can we do? we can't put # an in range arg on the select_many call :-( for tree in root.select_many(gtkaccessible.GtkTreeViewAccessible): # There will be some tree's that don't have a globalRect property # no idea why but we can just ignore them as we can be sure # this isn't the one we want. if "globalRect" not in tree.get_properties(): logger.debug("TreeView doesn't have globalRect property") continue # assume every treeview is in range unless we find out otherwise in_range = True i = 0 # Get a list of all ATK treeviews with globalRect within a # 5px range of this GtkTreeView # FIXME: is 5px too much?? It's unlikely more than one tree will # be within this range anyway, as they would be overlaying each # other. # Even if they are only one will be visible (we hope!) for r in self.globalRect: if r not in range(tree.globalRect[i] - 5, tree.globalRect[i] + 5): in_range = False i += 1 if in_range: treeviews.append(tree) return treeviews
class UbuntuKeyboardTests(AutopilotTestCase): @classmethod def setUpClass(cls): # FIXME: This is a work around re: lp:1238417 #### if model() != "Desktop": from autopilot.input import _uinput _uinput._touch_device = _uinput.create_touch_device() def setUp(self): if model() == "Desktop": self.skipTest("Ubuntu Keyboard tests only run on device.") super(UbuntuKeyboardTests, self).setUp() self.set_test_settings() sleep(5) # Have to give time for gsettings change to propogate self.pointer = Pointer(Touch.create()) def set_test_settings(self): gsettings = Gio.Settings.new("com.canonical.keyboard.maliit") gsettings.set_strv( "enabled-languages", ["en", "es", "de", "zh", "emoji"]) gsettings.set_string("active-language", "en") gsettings.set_string("previous-language", "es") gsettings.set_boolean("auto-capitalization", True) gsettings.set_boolean("auto-completion", True) gsettings.set_boolean("predictive-text", True) gsettings.set_boolean("spell-checking", True) gsettings.set_boolean("double-space-full-stop", True) def launch_test_input_area(self, label="", input_hints=None): self.app = self._launch_simple_input(label, input_hints) text_area = self.app.select_single("TextArea") return text_area def ensure_focus_on_input(self, input_area): self.pointer.click_object(input_area) keyboard = Keyboard() self.addCleanup(keyboard.dismiss) self.assertThat(keyboard.is_available, Eventually(Equals(True))) def _start_qml_script(self, script_contents): """Launch a qml script.""" qml_path = tempfile.mktemp(suffix='.qml') open(qml_path, 'w').write(script_contents) self.addCleanup(os.remove, qml_path) # Use installed desktop file so that Mir allows us to connect with # our test QML apps desktop_file = "/usr/share/applications/ubuntu-keyboard-tester.desktop" return self.launch_test_application( base.get_qmlscene_launch_command(), qml_path, '--desktop_file_hint=%s' % desktop_file, app_type='qt', ) def _write_test_desktop_file(self): desktop_file_dir = self.get_local_desktop_file_directory() if not os.path.exists(desktop_file_dir): os.makedirs(desktop_file_dir) with tempfile.NamedTemporaryFile( suffix='.desktop', dir=desktop_file_dir, delete=False ) as desktop_file: desktop_file.write( "[Desktop Entry]\n" "Type=Application\n" "Exec=Not important\n" "Path=Not important\n" "Name=Test app\n" "Icon=Not important" ) self.addCleanup(os.remove, desktop_file.name) return desktop_file.name def get_local_desktop_file_directory(self): return os.path.join( os.getenv('HOME'), '.local', 'share', 'applications' ) def _launch_simple_input(self, label="", input_hints=None): extra_script = "undefined" if input_hints is not None: extra_script = "|".join(input_hints) simple_script = dedent(""" import QtQuick 2.4 import Ubuntu.Components 1.3 Rectangle { id: window objectName: "windowRectangle" color: "lightgrey" Text { id: inputLabel text: "%(label)s" font.pixelSize: units.gu(3) anchors { left: input.left top: parent.top topMargin: 25 bottomMargin: 25 } } TextArea { id: input; objectName: "input" anchors.centerIn: parent inputMethodHints: %(input_method)s autoSize: true } } """ % {'label': label, 'input_method': extra_script}) return self._start_qml_script(simple_script)
class UbuntuHTML5TestCaseBase(AutopilotTestCase): BROWSER_CONTAINER_PATH = "{}/{}".format( os.path.dirname(os.path.realpath(__file__)), '../../tools/qml/webview.qml') INSTALLED_BROWSER_CONTAINER_PATH = \ '/usr/share/ubuntu-html5-ui-toolkit/tests/tools/qml/webview.qml' BROWSER_QML_APP_LAUNCHER = "/usr/lib/{}/qt5/bin/qmlscene".format( subprocess.check_output( ["dpkg-architecture", "-qDEB_HOST_MULTIARCH"]).strip().decode('utf-8')) # TODO: fix version LOCAL_HTML_EXAMPLES_PATH = os.path.abspath( "{}/{}".format( os.path.dirname(os.path.realpath(__file__)), '../../../../tests')) INSTALLED_HTML_EXAMPLES_PATH = \ '/usr/share/ubuntu-html5-ui-toolkit/tests/' APPS_SUBFOLDER_NAME = 'apps' BASE_PATH = '' def get_browser_container_path(self): if os.path.exists(self.BROWSER_CONTAINER_PATH): return self.BROWSER_CONTAINER_PATH return self.INSTALLED_BROWSER_CONTAINER_PATH def create_file_url_from(self, filepath): return 'file://' + filepath def setup_base_path(self): if os.path.exists(self.LOCAL_HTML_EXAMPLES_PATH): self.BASE_PATH = self.LOCAL_HTML_EXAMPLES_PATH else: self.BASE_PATH = self.INSTALLED_HTML_EXAMPLES_PATH def setUp(self): self.setup_base_path() if platform.model() == "Desktop": self.pointer = Pointer(Mouse.create()) else: self.pointer = Pointer(Touch.create()) params = [self.BROWSER_QML_APP_LAUNCHER, self.get_browser_container_path()] if (platform.model() != 'Desktop'): params.append( '--desktop_file_hint=/usr/share/" \ + "applications/unitywebappsqmllauncher.desktop') self.app = self.launch_test_application( *params, app_type='qt') self.webviewContainer = self.get_webviewContainer() self.watcher = self.webviewContainer.watch_signal( 'resultUpdated(QString)') super(UbuntuHTML5TestCaseBase, self).setUp() def tearDown(self): super(UbuntuHTML5TestCaseBase, self).tearDown() def pick_app_launcher(self, app_path): # force Qt app introspection: from autopilot.introspection.qt import QtApplicationLauncher return QtApplicationLauncher() def get_webviewContainer(self): return self.app.select_single(objectName="webviewContainer") def get_webview(self): return self.app.select_single(objectName="webview") def get_addressbar(self): return self.app.select_single(objectName="addressbar") def get_button(self): return self.app.select_single(objectName="browseButton") def get_title(self): return self.get_webview().title def assert_url_eventually_loaded(self, url): webview = self.get_webview() self.assertThat( webview.loadProgress, Eventually(Equals(100))) self.assertThat( webview.loading, Eventually(Equals(False))) self.assertThat( webview.url, Eventually(Equals(url))) def click_dom_node_with_id(self, id): webview = self.get_webviewContainer() webview.slots.clickElementById(id) self.assertThat( lambda: self.watcher.num_emissions, Eventually(Equals(1))) def click_any_dom_node_by_selector(self, selector): webview = self.get_webviewContainer() webview.slots.clickAnyElementBySelector(selector) self.assertThat( lambda: self.watcher.num_emissions, Eventually(Equals(1))) def is_dom_node_visible(self, id): webview = self.get_webviewContainer() prev_emissions = self.watcher.num_emissions webview.slots.isNodeWithIdVisible(id) self.assertThat( lambda: self.watcher.num_emissions, Eventually(GreaterThan(prev_emissions))) return json.loads( webview.get_signal_emissions( 'resultUpdated(QString)')[-1][0])['result'] def eval_expression_in_page_unsafe(self, expr): webview = self.get_webviewContainer() prev_emissions = self.watcher.num_emissions webview.slots.evalInPageUnsafe(expr) self.assertThat( lambda: self.watcher.num_emissions, Eventually(GreaterThan(prev_emissions))) return webview.get_signal_emissions('resultUpdated(QString)')[-1][0] def get_dom_node_id_attribute(self, id, attribute): webview = self.get_webviewContainer() prev_emissions = self.watcher.num_emissions webview.slots.getAttributeForElementWithId(id, attribute) self.assertThat( lambda: self.watcher.num_emissions, Eventually(GreaterThan(prev_emissions))) return json.loads( webview.get_signal_emissions( 'resultUpdated(QString)')[-1][0])['result'] def get_address_bar_action_button(self): addressbar = self.get_addressbar() return addressbar.select_single(objectName="browseButton") def browse_to_url(self, url): import time addressbar = self.get_addressbar() self.assertThat( addressbar.activeFocus, Eventually(Equals(True))) self.keyboard.type(url, 0.001) self.pointer.click_object(self.get_webview()) # XXX: very bad, but wont fix time.sleep(1) button = self.get_address_bar_action_button() self.pointer.move_to_object(button) self.pointer.press() # XXX: very bad, but wont fix time.sleep(1) self.pointer.release() self.assert_url_eventually_loaded(url) def browse_to_app(self, appname): appfilepath = os.path.abspath( self.BASE_PATH + '/data/html/' + self.APPS_SUBFOLDER_NAME + '/' + appname + '/index.html') APP_HTML_PATH = self.create_file_url_from(appfilepath) self.browse_to_url(APP_HTML_PATH) def browse_to_test_html(self, html_filename): self.browse_to_url( self.create_file_url_from( os.path.abspath( '{}/data/html/{}'.format( self.BASE_PATH, html_filename))))
class GtkTreeView(AutopilotGtkEmulatorBase): """ Emulator for a GtkTreeView instance """ def __init__(self, *args): super(GtkTreeView, self).__init__(*args) self.pointing_device = Pointer(Mouse.create()) def click(self, ): """ This simply clicks a treeview object """ self.pointing_device.click_object(self) expectThat(self.is_focus).equals(True) def select_item(self, labelText): """ Selects an item in a GtkTreeView by its UI label text :param labelText: The label value of the tree item as seen on the UI :returns: An object of the requested treeitem e.g. If you want to click say an item displaying 'Home' in a treeview then it would be:: treeitem = treeview.select_item('Home') treeitem.click() If for some reason this doesn't work then use the :func:`click()` function to get the treeviews focus """ logger.debug('Selecting "{0}" item'.format(labelText)) try: # lets try and get the corresponding GailTreeView so we can assure # we are selecting the item from the correct treeview treeview = self._get_gail_treeview() treeview_item = treeview.select_item(str(labelText)) except ValueError: # lets catch the exception and have one last go at selecting the # item from a root instance # This may return more than one though. logger.warning('Could not get corresponding ' 'GtkTreeViewAccessibleObject with globalRect {0}. ' 'Trying to select GtkTreeView item from root ' 'object instead'.format(self.globalRect)) root = self.get_root_instance() if root is None: raise ValueError("Emulator could not get a root instance") treeview_item = root.select_single('GtkCellTextAccessible', accessible_name=str(labelText)) if treeview_item is None: raise ValueError( "Could not select item with label '{0}'".format(labelText)) logger.debug('Corresponding Item Found in treeview. Returning item.') return treeview_item def select_item_by_index(self, index): """ Selects an item in a GtkTreeVIew by its index :param index: index of the list item :rtype: Object of the treeview item at the selected index """ treeview = self._get_gail_treeview() treeview_item = treeview.select_item_by_index(index) if treeview_item is None: raise ValueError( "Could not select item with index '{0}'".format(index)) return treeview_item def get_all_items(self, startWith=None): logger.debug('GtkTreeView.get_all_items()') treeview = self._get_gail_treeview() items = treeview.get_all_items(startWith) if items is None: raise ValueError("NoneType: Could not get list of items") return items def get_partition_table_dict(self, ): """ Returns a dict of named tuples generated by the list of items returned from get_all_items. This enables us to access any available table cell using the Row number and column name example usage: >>> treeview = self.app.select_single('GtkTreeView') >>> table = treeview.get_partition_table_dict() # we can now access any cell using Row number as Key and column name i.e table['Row Number'].ColumnName >>> item = table['Row2'].Mount We now have an introspectable object for that particular cell which we can use to either assert the properties of the cell and also click etc.... >>> self.assertThat(item.accessible_name, Equals('/home')) >>> self.mouse.click(item) """ # first get accessible tree treeview = self._get_gail_treeview() # Now each column header is a GtkButton, so we get the label from each # one and create a list tree_column_objects = treeview.select_many('GtkButtonAccessible') column_names = [] for column in tree_column_objects: # We are only interested in columns with headers. Blank columns # seem to usually be used for spacing and contain no cells if column.accessible_name == '': pass else: # strip all non alpaha chars name = re.sub(r'\W+', '', column.accessible_name) column_names.append(name) # Create a named tuple using the column headers, which enables access # to the column by name Columns = namedtuple('Columns', column_names) # generate a list of items tree_items = treeview.get_all_items() # lets create a temp list temp_list = [] # TODO: we actually don't really need this for item in tree_items: temp_list.append(item) # so we want to create a Columns tuple for each row in the table # therefore picking only the n items where n is the number of column # names start, end = 0, len(column_names) row_list, table_dict = [], {} for i in range(0, int(len(temp_list) / len(column_names))): # fill columns tuple row = Columns(*temp_list[start:end]) # create a new tuple adding the current row number # which we will use as dict key row_list.append(('Row{0}'.format(i + 1), row)) # update our table dict table_dict.update(row_list) # remove the items we just added from the temp list del temp_list[start:end] # return table_dict return table_dict def get_number_of_rows(self, ): items = self.get_partition_table_dict() return len(items) def _get_gail_treeview(self, ): """ Gets the GtkTreeViews corresponding GtkTreeViewAccessible object """ logger.debug('Getting corresponding GtkTreeViewAccessible object') # lets get a root instance root = self.get_root_instance() assert root is not None # As the treeview item is in the GAILWindow tree and not our current # tree We want to select the treeviewaccessible with the same # globalRect as us logger.debug('Selecting GtkTreeViewAccessible with same globalRect') treeviews = root.select_many('GtkTreeViewAccessible', globalRect=self.globalRect) # if the treeviews are nested they could potentially have the # same globalRect so lets pick out the one thats visible for treeview in treeviews: if treeview.visible: logger.debug('GtkTreeViewAccessible object found, ' 'returning object.') return treeview raise ValueError("No treeview visible with globalRect {0}".format( self.globalRect))
class QtCreatorTestCase(AutopilotTestCase): def setUp(self): self.pointing_device = Pointer(Mouse.create()) # sdk_test_mode = os.environ['SDK_TEST_MODE'] sdk_test_mode = os.environ.get('SDK_TEST_MODE', 'auto') if sdk_test_mode != 'manual': self._set_temporary_home_directory() self._set_click_chroot_suffix() super(QtCreatorTestCase, self).setUp() self.launch_qt_creator() def launch_qt_creator(self): # self.patch_environment('HOME','/home/balogh') self.ide = self.launch_test_application('qtcreator') def _create_temporary_directory(self): self.temporary_directory = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, self.temporary_directory) def _set_temporary_home_directory(self): self._create_temporary_directory() sourcedir = os.environ['HOME'] + "/.bazaar" destdir = self.temporary_directory + "/.bazaar" shutil.copytree(sourcedir, destdir, symlinks=False, ignore=None) sourcedir = os.environ['HOME'] + "/.config/QtProject/qtcreator" destdir = self.temporary_directory + "/.config/QtProject/qtcreator" shutil.copytree(sourcedir, destdir, symlinks=False, ignore=None) sourcedir = os.environ['HOME'] + "/.config/ubuntu-sdk" destdir = self.temporary_directory + "/.config/ubuntu-sdk" shutil.copytree(sourcedir, destdir, symlinks=False, ignore=None) sourcedir = os.environ[ 'HOME'] + "/.local/share/data/QtProject/qtcreator" destdir = self.temporary_directory + "/.local/share/data/QtProject/qtcreator" shutil.copytree(sourcedir, destdir, symlinks=False, ignore=None) self.patch_environment('HOME', self.temporary_directory) print os.environ['HOME'] os.chdir(os.environ['HOME']) if not os.path.exists('.config/ubuntu-sdk'): os.makedirs('.config/ubuntu-sdk') open('.config/ubuntu-sdk/firstrun', 'w') def _set_click_chroot_suffix(self): ts = time.time() st = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d%H%M%S') os.environ["CLICK_CHROOT_SUFFIX"] = "testing" + st def _get_main_window(self): return self.ide.wait_select_single('Core::Internal::MainWindow') def _get_welcome_tab_view(self): return self.ide.wait_select_single( 'QWidgetWindow', objectName='Core::Internal::MainWindowClassWindow') def _get_left_tabbar(self): main_window = self._get_main_window() return main_window.select_single('Core::Internal::FancyTabBar') def _get_number_of_tabs(self): tabs = self._get_left_tabbar().select_many('Core::Internal::FancyTab') return len(tabs) def _get_current_active_tab_name(self): return self._get_left_tabbar().selectedTabLabel def _get_new_project_button(self): return self._get_welcome_tab_view().wait_select_single( 'Button', text='New Project') def _get_new_project_dialog(self): return self._get_main_window().wait_select_single( 'Core::Internal::NewDialog') def _click_new_project_dialog_choose_button(self): button = self._get_new_project_dialog().select_single( 'QPushButton', text='&Choose...') self.pointing_device.click_object(button) def _get_new_project_wizard_dialog(self): return self.ide.wait_select_single( 'Ubuntu::Internal::UbuntuProjectApplicationWizardDialog') def _get_new_project_name_input_field(self): return self._get_new_project_wizard_dialog().select_single( 'Utils::ProjectNameValidatingLineEdit') def _get_new_project_location_field(self): return self._get_new_project_wizard_dialog().select_single( 'Utils::PathChooser') def _clear_input_field(self, input_field): self.pointing_device.click_object(input_field) self.pointing_device.click() self.pointing_device.click() self.keyboard.press_and_release('Backspace') def _type_new_project_name(self, project): input_field = self._get_new_project_name_input_field() self._clear_input_field(input_field) self.keyboard.type(project) def _type_new_project_location(self, location): location_field = self._get_new_project_location_field() self._clear_input_field(location_field) self.keyboard.type(location) def click_new_project_button(self): new_button = self._get_new_project_button() self.pointing_device.click_object(new_button) return self._get_new_project_dialog() def _get_wizard_finish_button(self): return self._get_new_project_wizard_dialog().select_single( 'QPushButton', text='&Finish') def _get_wizard_next_button(self): return self._get_new_project_wizard_dialog().select_single( 'QPushButton', text='&Next >') def _click_wizard_finish_button(self): finish_button = self._get_wizard_finish_button() self.pointing_device.click_object(finish_button) def _click_wizard_next_button(self): next_button = self._get_wizard_next_button() self.pointing_device.click_object(next_button) def _createAndOpenProject(self, typeString, name): """ Open the New File and Project dialog by triggering the right action """ action = self.ide.wait_select_single('QAction', text='&New File or Project...') action.slots.trigger() new_project_dialog = self._get_main_window().wait_select_single( 'Core::Internal::NewDialog') """ Choose the App with Simple UI template in the Ubuntu category """ ubuntu_modelindex = new_project_dialog.wait_select_single( 'QModelIndex', text=' Ubuntu') self.pointing_device.click_object(ubuntu_modelindex) app_with_simple_ui_modelindex = new_project_dialog.wait_select_single( 'QModelIndex', text=typeString) self.pointing_device.click_object(app_with_simple_ui_modelindex) choose_pushbutton = new_project_dialog.wait_select_single( 'QPushButton', text='Choose...') self.pointing_device.click_object(choose_pushbutton) application_wizard_dialog = self._get_main_window().wait_select_single( 'Ubuntu::Internal::UbuntuProjectApplicationWizardDialog') """ Clear the default project name and enter the test name to the edit line and hit the Next->Next->Finish buttons """ projectname_lineedit = application_wizard_dialog.wait_select_single( 'Utils::ProjectNameValidatingLineEdit') projectname_lineedit.slots.clear() projectname_lineedit.slots.setText(name) next_pushbutton = application_wizard_dialog.wait_select_single( 'QPushButton', text='&Next >') next_pushbutton.slots.click() next_pushbutton = application_wizard_dialog.wait_select_single( 'QPushButton', text='&Next >') next_pushbutton.slots.click() for index, checkbox_kit in enumerate( application_wizard_dialog.select_many('QCheckBox')): if re.search('GCC ubuntu-sdk', checkbox_kit.text): checkbox_kit.slots.setChecked(True) checkbox_kit = application_wizard_dialog.wait_select_single( 'QCheckBox', text='Desktop') checkbox_kit.slots.setChecked(False) next_pushbutton = application_wizard_dialog.wait_select_single( 'QPushButton', text='&Next >') next_pushbutton.slots.click() next_pushbutton = application_wizard_dialog.wait_select_single( 'QPushButton', text='&Finish') next_pushbutton.slots.click() def switch_to_tab_by_name(self, tab_name): current_tab = self._get_current_active_tab_name() if tab_name == current_tab: return tabbar = self._get_left_tabbar() tabbar_height = tabbar.height number_of_tabs = self._get_number_of_tabs() tbar_x, tbar_y, tbar_width, tbar_height = tabbar.globalRect tab_number = 1 while current_tab != tab_name and not tab_number > number_of_tabs: tab_center = ((tabbar_height / number_of_tabs) * tab_number) - \ ((tabbar_height / number_of_tabs) / 2) tx = tbar_x + tbar_width / 2 ty = tbar_y + tab_center self.pointing_device.move(tx, ty) self.pointing_device.click() current_tab = self._get_current_active_tab_name() tab_number += 1